diff --git a/assets/.prettierrc.yml b/assets/.prettierrc.yml index 05ab046f..83cfc971 100644 --- a/assets/.prettierrc.yml +++ b/assets/.prettierrc.yml @@ -7,7 +7,7 @@ bracketSpacing: true endOfLine: lf quoteProps: as-needed trailingComma: all -arrowParens: always +arrowParens: avoid overrides: - files: "*.css" options: diff --git a/assets/js/__tests__/ujs.spec.ts b/assets/js/__tests__/ujs.spec.ts index 282eb404..6833679e 100644 --- a/assets/js/__tests__/ujs.spec.ts +++ b/assets/js/__tests__/ujs.spec.ts @@ -70,10 +70,10 @@ describe('Remote utilities', () => { }); it('should emit fetchcomplete event', () => - new Promise((resolve) => { + new Promise(resolve => { let a: HTMLAnchorElement | null = null; - addOneShotEventListener('fetchcomplete', (event) => { + addOneShotEventListener('fetchcomplete', event => { expect(event.target).toBe(a); resolve(); }); @@ -95,8 +95,8 @@ describe('Remote utilities', () => { }; it('should submit a form with the given action', () => - new Promise((resolve) => { - addOneShotEventListener('submit', (event) => { + new Promise(resolve => { + addOneShotEventListener('submit', event => { event.preventDefault(); const target = assertType(event.target, HTMLFormElement); @@ -192,10 +192,10 @@ describe('Remote utilities', () => { }); it('should emit fetchcomplete event', () => - new Promise((resolve) => { + new Promise(resolve => { let form: HTMLFormElement | null = null; - addOneShotEventListener('fetchcomplete', (event) => { + addOneShotEventListener('fetchcomplete', event => { expect(event.target).toBe(form); resolve(); }); @@ -214,7 +214,7 @@ describe('Remote utilities', () => { describe('Form utilities', () => { beforeEach(() => { - vi.spyOn(window, 'requestAnimationFrame').mockImplementation((cb) => { + vi.spyOn(window, 'requestAnimationFrame').mockImplementation(cb => { cb(1); return 1; }); @@ -260,7 +260,7 @@ describe('Form utilities', () => { // jsdom has no implementation for HTMLFormElement.prototype.submit // and will return an error if the event's default isn't prevented - form.addEventListener('submit', (event) => event.preventDefault()); + form.addEventListener('submit', event => event.preventDefault()); const button = document.createElement('button'); button.type = 'submit'; diff --git a/assets/js/__tests__/upload.spec.ts b/assets/js/__tests__/upload.spec.ts index 1003b522..9a1d7c4c 100644 --- a/assets/js/__tests__/upload.spec.ts +++ b/assets/js/__tests__/upload.spec.ts @@ -137,8 +137,8 @@ describe('Image upload form', () => { const failedUnloadEvent = new Event('beforeunload', { cancelable: true }); expect(fireEvent(window, failedUnloadEvent)).toBe(false); - await new Promise((resolve) => { - form.addEventListener('submit', (event) => { + await new Promise(resolve => { + form.addEventListener('submit', event => { event.preventDefault(); resolve(); }); @@ -153,7 +153,7 @@ describe('Image upload form', () => { fetchMock.mockResolvedValue(new Response(JSON.stringify(scrapeResponse), { status: 200 })); fireEvent.input(remoteUrl, { target: { value: 'http://localhost/images/1' } }); - await new Promise((resolve) => { + await new Promise(resolve => { tagsEl.addEventListener('addtag', (event: Event) => { expect((event as CustomEvent).detail).toEqual({ name: 'artist:test' }); resolve(); diff --git a/assets/js/autocomplete.js b/assets/js/autocomplete.js index 01ea2893..1a95fb04 100644 --- a/assets/js/autocomplete.js +++ b/assets/js/autocomplete.js @@ -139,7 +139,7 @@ function createList(suggestions) { list = document.createElement('ul'); list.className = 'autocomplete__list'; - suggestions.forEach((suggestion) => createItem(list, suggestion)); + suggestions.forEach(suggestion => createItem(list, suggestion)); parent.appendChild(list); } @@ -176,7 +176,7 @@ function showAutocomplete(suggestions, fetchedTerm, targetInput) { function getSuggestions(term) { // In case source URL was not given at all, do not try sending the request. if (!inputField.dataset.acSource) return []; - return fetch(`${inputField.dataset.acSource}${term}`).then((response) => response.json()); + return fetch(`${inputField.dataset.acSource}${term}`).then(response => response.json()); } function getSelectedTerm() { @@ -212,7 +212,7 @@ function listenAutocomplete() { document.addEventListener('focusin', fetchLocalAutocomplete); - document.addEventListener('input', (event) => { + document.addEventListener('input', event => { removeParent(); fetchLocalAutocomplete(event); window.clearTimeout(timeout); @@ -258,7 +258,7 @@ function listenAutocomplete() { showAutocomplete(cache[fetchedTerm], fetchedTerm, event.target); } else { // inputField could get overwritten while the suggestions are being fetched - use event.target - getSuggestions(fetchedTerm).then((suggestions) => { + getSuggestions(fetchedTerm).then(suggestions => { if (fetchedTerm === event.target.value) { showAutocomplete(suggestions, fetchedTerm, event.target); } @@ -269,7 +269,7 @@ function listenAutocomplete() { }); // If there's a click outside the inputField, remove autocomplete - document.addEventListener('click', (event) => { + document.addEventListener('click', event => { if (event.target && event.target !== inputField) removeParent(); if (event.target === inputField && isSearchField() && isSelectionOutsideCurrentTerm()) removeParent(); }); @@ -283,8 +283,8 @@ function listenAutocomplete() { fetch(`/autocomplete/compiled?vsn=2&key=${cacheKey}`, { credentials: 'omit', cache: 'force-cache' }) .then(handleError) - .then((resp) => resp.arrayBuffer()) - .then((buf) => { + .then(resp => resp.arrayBuffer()) + .then(buf => { localAc = new LocalAutocompleter(buf); }); } diff --git a/assets/js/booru.js b/assets/js/booru.js index 45f30680..3c58a7cf 100644 --- a/assets/js/booru.js +++ b/assets/js/booru.js @@ -27,7 +27,7 @@ function isStale(tag) { } function clearTags() { - Object.keys(localStorage).forEach((key) => { + Object.keys(localStorage).forEach(key => { if (key.substring(0, 9) === 'bor_tags_') { store.remove(key); } @@ -84,8 +84,8 @@ function fetchAndPersistTags(tagIds) { const remaining = tagIds.slice(41); fetch(`/fetch/tags?ids[]=${ids.join('&ids[]=')}`) - .then((response) => response.json()) - .then((data) => data.tags.forEach((tag) => persistTag(tag))) + .then(response => response.json()) + .then(data => data.tags.forEach(tag => persistTag(tag))) .then(() => fetchAndPersistTags(remaining)); } @@ -96,7 +96,7 @@ function fetchAndPersistTags(tagIds) { function fetchNewOrStaleTags(tagIds) { const fetchIds = []; - tagIds.forEach((t) => { + tagIds.forEach(t => { const stored = store.get(`bor_tags_${t}`); if (!stored || isStale(stored)) { fetchIds.push(t); diff --git a/assets/js/boorujs.js b/assets/js/boorujs.js index 6ccfa0e4..7f127f80 100644 --- a/assets/js/boorujs.js +++ b/assets/js/boorujs.js @@ -26,27 +26,27 @@ const types = { const actions = { hide(data) { - selectorCb(data.base, data.value, (el) => el.classList.add('hidden')); + selectorCb(data.base, data.value, el => el.classList.add('hidden')); }, tabHide(data) { - selectorCbChildren(data.base, data.value, (el) => el.classList.add('hidden')); + selectorCbChildren(data.base, data.value, el => el.classList.add('hidden')); }, show(data) { - selectorCb(data.base, data.value, (el) => el.classList.remove('hidden')); + selectorCb(data.base, data.value, el => el.classList.remove('hidden')); }, toggle(data) { - selectorCb(data.base, data.value, (el) => el.classList.toggle('hidden')); + selectorCb(data.base, data.value, el => el.classList.toggle('hidden')); }, submit(data) { - selectorCb(data.base, data.value, (el) => el.submit()); + selectorCb(data.base, data.value, el => el.submit()); }, disable(data) { - selectorCb(data.base, data.value, (el) => { + selectorCb(data.base, data.value, el => { el.disabled = true; }); }, @@ -65,7 +65,7 @@ const actions = { }, checkall(data) { - $$(`${data.value} input[type=checkbox]`).forEach((c) => { + $$(`${data.value} input[type=checkbox]`).forEach(c => { c.checked = !c.checked; }); }, @@ -102,8 +102,8 @@ const actions = { if (loadTab && !newTab.dataset.loaded) { fetchHtml(loadTab) .then(handleError) - .then((response) => response.text()) - .then((response) => { + .then(response => response.text()) + .then(response => { newTab.innerHTML = response; }) .then(() => { diff --git a/assets/js/burger.ts b/assets/js/burger.ts index a22b06ad..58c416bb 100644 --- a/assets/js/burger.ts +++ b/assets/js/burger.ts @@ -40,7 +40,7 @@ function copyUserLinksTo(burger: HTMLElement) { } }; - $$('.js-burger-links').forEach((container) => copy(container.children)); + $$('.js-burger-links').forEach(container => copy(container.children)); } export function setupBurgerMenu() { @@ -53,7 +53,7 @@ export function setupBurgerMenu() { copyUserLinksTo(burger); - toggle.addEventListener('click', (event) => { + toggle.addEventListener('click', event => { event.stopPropagation(); event.preventDefault(); diff --git a/assets/js/comment.js b/assets/js/comment.js index b60a6fec..b28bcd31 100644 --- a/assets/js/comment.js +++ b/assets/js/comment.js @@ -27,7 +27,7 @@ function commentPosted(response) { commentEditForm.reset(); if (requestOk) { - response.text().then((text) => { + response.text().then(text => { if (text.includes('
')) { window.location.reload(); } else { @@ -60,7 +60,7 @@ function loadParentPost(event) { fetchHtml(`/images/${imageId}/comments/${commentId}`) .then(handleError) - .then((data) => { + .then(data => { clearParentPost(clickedLink, fullComment); insertParentPost(data, clickedLink, fullComment); }); @@ -97,7 +97,7 @@ function clearParentPost(clickedLink, fullComment) { } // Remove class active_reply_link from all links in the comment - [].slice.call(fullComment.getElementsByClassName('active_reply_link')).forEach((link) => { + [].slice.call(fullComment.getElementsByClassName('active_reply_link')).forEach(link => { link.classList.remove('active_reply_link'); }); @@ -129,7 +129,7 @@ function loadComments(event) { fetchHtml(getURL) .then(handleError) - .then((data) => { + .then(data => { displayComments(container, data); // Make sure the :target CSS selector applies to the inserted content @@ -165,7 +165,7 @@ function setupComments() { '#js-refresh-comments': loadComments, }; - document.addEventListener('click', (event) => { + document.addEventListener('click', event => { if (event.button === 0) { // Left-click only for (const target in targets) { @@ -176,7 +176,7 @@ function setupComments() { } }); - document.addEventListener('fetchcomplete', (event) => { + document.addEventListener('fetchcomplete', event => { if (event.target.id === 'js-comment-form') commentPosted(event.detail); }); } diff --git a/assets/js/fp.ts b/assets/js/fp.ts index 25fc7bd9..8302029d 100644 --- a/assets/js/fp.ts +++ b/assets/js/fp.ts @@ -102,8 +102,8 @@ function getUserAgentBrands(): string { // NB: Chromium implements GREASE protocol to prevent ossification of // the "Not a brand" string - see https://stackoverflow.com/a/64443187 brands = data.brands - .filter((e) => !e.brand.match(/.*ot.*rand.*/gi)) - .map((e) => `${e.brand}${e.version}`) + .filter(e => !e.brand.match(/.*ot.*rand.*/gi)) + .map(e => `${e.brand}${e.version}`) .sort() .join(''); } diff --git a/assets/js/galleries.ts b/assets/js/galleries.ts index 73f0a0b6..bf00c3c6 100644 --- a/assets/js/galleries.ts +++ b/assets/js/galleries.ts @@ -22,7 +22,7 @@ export function setupGalleryEditing() { initDraggables(); - $$('.media-box', containerEl).forEach((i) => { + $$('.media-box', containerEl).forEach(i => { i.draggable = true; }); @@ -35,7 +35,7 @@ export function setupGalleryEditing() { sortableEl.classList.remove('editing'); containerEl.classList.remove('drag-container'); - newImages = $$('.image-container', containerEl).map((i) => + newImages = $$('.image-container', containerEl).map(i => parseInt(assertNotUndefined(i.dataset.imageId), 10), ); diff --git a/assets/js/graph.ts b/assets/js/graph.ts index 035e33ed..19dc00d2 100644 --- a/assets/js/graph.ts +++ b/assets/js/graph.ts @@ -22,7 +22,7 @@ function graphSlice(el: SVGSVGElement, width: number, offset: number) { } function resizeGraphs() { - $$('#js-graph-svg').forEach((el) => { + $$('#js-graph-svg').forEach(el => { const parent: HTMLElement | null = el.parentElement; if (parent) { @@ -47,7 +47,7 @@ function scaleGraph(target: HTMLElement, min: number, max: number) { } function setupSliders() { - $$('#js-graph-slider').forEach((el) => { + $$('#js-graph-slider').forEach(el => { const targetId = el.getAttribute('data-target'); if (!targetId) return; diff --git a/assets/js/image_expansion.js b/assets/js/image_expansion.js index 78d90ee3..10f1130e 100644 --- a/assets/js/image_expansion.js +++ b/assets/js/image_expansion.js @@ -156,7 +156,7 @@ function bindImageForClick(target) { } function bindImageTarget(node = document) { - $$('.image-target', node).forEach((target) => { + $$('.image-target', node).forEach(target => { pickAndResize(target); if (target.dataset.mimeType === 'video/webm') { diff --git a/assets/js/imagesclientside.ts b/assets/js/imagesclientside.ts index 2d6d8141..8ea43a54 100644 --- a/assets/js/imagesclientside.ts +++ b/assets/js/imagesclientside.ts @@ -84,15 +84,15 @@ export function filterNode(node: Pick) { // Image thumb boxes with vote and fave buttons on them $$('.image-container', node) - .filter((img) => !run(img, hiddenTags, hiddenFilter, hideThumbTyped)) - .filter((img) => !run(img, spoileredTags, spoileredFilter, spoilerThumbTyped)) - .forEach((img) => showThumb(img)); + .filter(img => !run(img, hiddenTags, hiddenFilter, hideThumbTyped)) + .filter(img => !run(img, spoileredTags, spoileredFilter, spoilerThumbTyped)) + .forEach(img => showThumb(img)); // Individual image pages and images in posts/comments $$('.image-show-container', node) - .filter((img) => !run(img, hiddenTags, hiddenFilter, hideBlockTyped)) - .filter((img) => !run(img, spoileredTags, spoileredFilter, spoilerBlockTyped)) - .forEach((img) => showBlock(img)); + .filter(img => !run(img, hiddenTags, hiddenFilter, hideBlockTyped)) + .filter(img => !run(img, spoileredTags, spoileredFilter, spoilerBlockTyped)) + .forEach(img => showBlock(img)); } export function initImagesClientside() { diff --git a/assets/js/input-duplicator.ts b/assets/js/input-duplicator.ts index 6ce8a502..57cbc1f4 100644 --- a/assets/js/input-duplicator.ts +++ b/assets/js/input-duplicator.ts @@ -41,7 +41,7 @@ export function inputDuplicatorCreator({ const maxOptionCountElement = assertNotNull($(maxInputCountSelector, form)); const maxOptionCount = parseInt(maxOptionCountElement.innerHTML, 10); - addButton.addEventListener('click', (e) => { + addButton.addEventListener('click', e => { e.preventDefault(); const existingFields = $$(fieldSelector, form); @@ -52,7 +52,7 @@ export function inputDuplicatorCreator({ const prevField = existingFields[existingFieldsLength - 1]; const prevFieldCopy = prevField.cloneNode(true) as HTMLElement; - $$('input', prevFieldCopy).forEach((prevFieldCopyInput) => { + $$('input', prevFieldCopy).forEach(prevFieldCopyInput => { // Reset new input's value prevFieldCopyInput.value = ''; prevFieldCopyInput.removeAttribute('value'); diff --git a/assets/js/interactions.js b/assets/js/interactions.js index fac8b5e9..fc9994a8 100644 --- a/assets/js/interactions.js +++ b/assets/js/interactions.js @@ -39,33 +39,33 @@ function modifyCache(callback) { } function cacheStatus(imageId, interactionType, value) { - modifyCache((cache) => { + modifyCache(cache => { cache[`${imageId}${interactionType}`] = { imageId, interactionType, value }; return cache; }); } function uncacheStatus(imageId, interactionType) { - modifyCache((cache) => { + modifyCache(cache => { delete cache[`${imageId}${interactionType}`]; return cache; }); } function setScore(imageId, data) { - onImage(imageId, '.score', (el) => { + onImage(imageId, '.score', el => { el.textContent = data.score; }); - onImage(imageId, '.favorites', (el) => { + onImage(imageId, '.favorites', el => { el.textContent = data.faves; }); - onImage(imageId, '.upvotes', (el) => { + onImage(imageId, '.upvotes', el => { el.textContent = data.upvotes; }); - onImage(imageId, '.downvotes', (el) => { + onImage(imageId, '.downvotes', el => { el.textContent = data.downvotes; }); } @@ -75,50 +75,50 @@ function setScore(imageId, data) { function showUpvoted(imageId) { cacheStatus(imageId, 'voted', 'up'); - onImage(imageId, '.interaction--upvote', (el) => el.classList.add('active')); + onImage(imageId, '.interaction--upvote', el => el.classList.add('active')); } function showDownvoted(imageId) { cacheStatus(imageId, 'voted', 'down'); - onImage(imageId, '.interaction--downvote', (el) => el.classList.add('active')); + onImage(imageId, '.interaction--downvote', el => el.classList.add('active')); } function showFaved(imageId) { cacheStatus(imageId, 'faved', ''); - onImage(imageId, '.interaction--fave', (el) => el.classList.add('active')); + onImage(imageId, '.interaction--fave', el => el.classList.add('active')); } function showHidden(imageId) { cacheStatus(imageId, 'hidden', ''); - onImage(imageId, '.interaction--hide', (el) => el.classList.add('active')); + onImage(imageId, '.interaction--hide', el => el.classList.add('active')); } function resetVoted(imageId) { uncacheStatus(imageId, 'voted'); - onImage(imageId, '.interaction--upvote', (el) => el.classList.remove('active')); + onImage(imageId, '.interaction--upvote', el => el.classList.remove('active')); - onImage(imageId, '.interaction--downvote', (el) => el.classList.remove('active')); + onImage(imageId, '.interaction--downvote', el => el.classList.remove('active')); } function resetFaved(imageId) { uncacheStatus(imageId, 'faved'); - onImage(imageId, '.interaction--fave', (el) => el.classList.remove('active')); + onImage(imageId, '.interaction--fave', el => el.classList.remove('active')); } function resetHidden(imageId) { uncacheStatus(imageId, 'hidden'); - onImage(imageId, '.interaction--hide', (el) => el.classList.remove('active')); + onImage(imageId, '.interaction--hide', el => el.classList.remove('active')); } function interact(type, imageId, method, data = {}) { return fetchJson(method, endpoints[type](imageId), data) - .then((res) => res.json()) - .then((res) => setScore(imageId, res)); + .then(res => res.json()) + .then(res => setScore(imageId, res)); } function displayInteractionSet(interactions) { - interactions.forEach((i) => { + interactions.forEach(i => { switch (i.interaction_type) { case 'faved': showFaved(i.image_id); @@ -143,8 +143,8 @@ function loadInteractions() { if (!document.getElementById('imagelist-container')) return; /* Users will blind downvote without this */ - window.booru.imagesWithDownvotingDisabled.forEach((i) => { - onImage(i, '.interaction--downvote', (a) => { + window.booru.imagesWithDownvotingDisabled.forEach(i => { + onImage(i, '.interaction--downvote', a => { // TODO Use a 'js-' class to target these instead const icon = a.querySelector('i') || a.querySelector('.oc-icon-small'); @@ -152,7 +152,7 @@ function loadInteractions() { a.classList.add('disabled'); a.addEventListener( 'click', - (event) => { + event => { event.stopPropagation(); event.preventDefault(); }, @@ -205,7 +205,7 @@ const targets = { }; function bindInteractions() { - document.addEventListener('click', (event) => { + document.addEventListener('click', event => { if (event.button === 0) { // Is it a left-click? for (const target in targets) { @@ -222,7 +222,7 @@ function bindInteractions() { } function loggedOutInteractions() { - [].forEach.call(document.querySelectorAll('.interaction--fave,.interaction--upvote,.interaction--downvote'), (a) => + [].forEach.call(document.querySelectorAll('.interaction--fave,.interaction--upvote,.interaction--downvote'), a => a.setAttribute('href', '/sessions/new'), ); } diff --git a/assets/js/markdowntoolbar.js b/assets/js/markdowntoolbar.js index 93ce1af9..47a0e104 100644 --- a/assets/js/markdowntoolbar.js +++ b/assets/js/markdowntoolbar.js @@ -156,13 +156,13 @@ function insertLink(textarea, options) { } function wrapSelection(textarea, options) { - transformSelection(textarea, (selectedText) => { + transformSelection(textarea, selectedText => { const { text = selectedText, prefix = '', suffix = options.prefix } = options, emptyText = text === ''; let newText = text; if (!emptyText) { - newText = text.replace(/(\n{2,})/g, (match) => { + newText = text.replace(/(\n{2,})/g, match => { return suffix + match + prefix; }); } @@ -188,7 +188,7 @@ function wrapLines(textarea, options, eachLine = true) { ? prefix + text.trim() + suffix : text .split(/\n/g) - .map((line) => prefix + line.trim() + suffix) + .map(line => prefix + line.trim() + suffix) .join('\n'); // Force a space at the end of lines with only blockquote markers @@ -205,7 +205,7 @@ function wrapSelectionOrLines(textarea, options) { } function escapeSelection(textarea, options) { - transformSelection(textarea, (selectedText) => { + transformSelection(textarea, selectedText => { const { text = selectedText } = options, emptyText = text === ''; @@ -255,10 +255,10 @@ function shortcutHandler(event) { } function setupToolbar() { - $$('.communication__toolbar').forEach((toolbar) => { + $$('.communication__toolbar').forEach(toolbar => { toolbar.addEventListener('click', clickHandler); }); - $$('.js-toolbar-input').forEach((textarea) => { + $$('.js-toolbar-input').forEach(textarea => { textarea.addEventListener('keydown', shortcutHandler); }); } diff --git a/assets/js/misc.ts b/assets/js/misc.ts index ef9eb7f9..65c4e0ed 100644 --- a/assets/js/misc.ts +++ b/assets/js/misc.ts @@ -20,7 +20,7 @@ function formResult({ target, detail }: FetchcompleteEvent) { hideEl(formEl); showEl(resultEl); - $$('input[type="submit"],button', formEl).forEach((button) => { + $$('input[type="submit"],button', formEl).forEach(button => { button.disabled = false; }); } @@ -30,7 +30,7 @@ function formResult({ target, detail }: FetchcompleteEvent) { const form = assertType(target, HTMLFormElement); const result = assertNotNull($(resultSelector)); - detail.text().then((text) => showResult(form, result, text)); + detail.text().then(text => showResult(form, result, text)); } } } @@ -85,7 +85,7 @@ export function setupEvents() { } if (store.get('hide_score')) { - $$('.upvotes,.score,.downvotes').forEach((s) => hideEl(s)); + $$('.upvotes,.score,.downvotes').forEach(s => hideEl(s)); } document.addEventListener('fetchcomplete', formResult); diff --git a/assets/js/notifications.ts b/assets/js/notifications.ts index 4d4757b9..7d007b26 100644 --- a/assets/js/notifications.ts +++ b/assets/js/notifications.ts @@ -13,10 +13,10 @@ const NOTIFICATION_INTERVAL = 600000, function bindSubscriptionLinks() { delegate(document, 'fetchcomplete', { - '.js-subscription-link': (event) => { + '.js-subscription-link': event => { const target = assertNotNull(event.target.closest('.js-subscription-target')); - event.detail.text().then((text) => { + event.detail.text().then(text => { target.outerHTML = text; }); }, @@ -30,7 +30,7 @@ function getNewNotifications() { fetchJson('GET', '/notifications/unread') .then(handleError) - .then((response) => response.json()) + .then(response => response.json()) .then(({ notifications }) => { updateNotificationTicker(notifications); storeNotificationCount(notifications); diff --git a/assets/js/preview.js b/assets/js/preview.js index 6988b3c0..21dc43a4 100644 --- a/assets/js/preview.js +++ b/assets/js/preview.js @@ -47,7 +47,7 @@ function getPreview(body, anonymous, previewLoading, previewIdle, previewContent fetchJson('POST', path, { body, anonymous }) .then(handleError) - .then((data) => { + .then(data => { previewContent.innerHTML = data; filterNode(previewContent); bindImageTarget(previewContent); @@ -117,7 +117,7 @@ function setupPreviews() { updatePreview(); }); - document.addEventListener('click', (event) => { + document.addEventListener('click', event => { if (event.target && event.target.closest('.post-reply')) { const link = event.target.closest('.post-reply'); commentReply(link.dataset.author, link.getAttribute('href'), textarea, link.dataset.post); diff --git a/assets/js/query/boolean.ts b/assets/js/query/boolean.ts index 6f2afe96..68a0b107 100644 --- a/assets/js/query/boolean.ts +++ b/assets/js/query/boolean.ts @@ -1,11 +1,11 @@ import { AstMatcher } from './types'; export function matchAny(...matchers: AstMatcher[]): AstMatcher { - return (e: HTMLElement) => matchers.some((matcher) => matcher(e)); + return (e: HTMLElement) => matchers.some(matcher => matcher(e)); } export function matchAll(...matchers: AstMatcher[]): AstMatcher { - return (e: HTMLElement) => matchers.every((matcher) => matcher(e)); + return (e: HTMLElement) => matchers.every(matcher => matcher(e)); } export function matchNot(matcher: AstMatcher): AstMatcher { diff --git a/assets/js/query/date.ts b/assets/js/query/date.ts index 17b1e589..a3404afd 100644 --- a/assets/js/query/date.ts +++ b/assets/js/query/date.ts @@ -17,16 +17,16 @@ function makeMatcher(bottomDate: PosixTimeMs, topDate: PosixTimeMs, qual: RangeE // done compared to numeric ranges. switch (qual) { case 'lte': - return (v) => new Date(v).getTime() < topDate; + return v => new Date(v).getTime() < topDate; case 'gte': - return (v) => new Date(v).getTime() >= bottomDate; + return v => new Date(v).getTime() >= bottomDate; case 'lt': - return (v) => new Date(v).getTime() < bottomDate; + return v => new Date(v).getTime() < bottomDate; case 'gt': - return (v) => new Date(v).getTime() >= topDate; + return v => new Date(v).getTime() >= topDate; case 'eq': default: - return (v) => { + return v => { const t = new Date(v).getTime(); return t >= bottomDate && t < topDate; }; diff --git a/assets/js/query/number.ts b/assets/js/query/number.ts index 5fe08e72..8c42db30 100644 --- a/assets/js/query/number.ts +++ b/assets/js/query/number.ts @@ -2,7 +2,7 @@ import { FieldMatcher, RangeEqualQualifier } from './types'; export function makeNumberMatcher(term: number, fuzz: number, qual: RangeEqualQualifier): FieldMatcher { // Range matching. - return (v) => { + return v => { const attrVal = parseFloat(v); if (isNaN(attrVal)) { diff --git a/assets/js/query/user.ts b/assets/js/query/user.ts index 2b8dbfe8..1410813f 100644 --- a/assets/js/query/user.ts +++ b/assets/js/query/user.ts @@ -8,7 +8,7 @@ function interactionMatch( interactions: Interaction[], ): boolean { return interactions.some( - (v) => v.image_id === imageId && v.interaction_type === type && (value === null || v.value === value), + v => v.image_id === imageId && v.interaction_type === type && (value === null || v.value === value), ); } diff --git a/assets/js/quick-tag.js b/assets/js/quick-tag.js index e43b460e..c75a37d5 100644 --- a/assets/js/quick-tag.js +++ b/assets/js/quick-tag.js @@ -30,10 +30,10 @@ function toggleActiveState() { setTagButton(`Submit (${currentTags()})`); - $$('.media-box__header').forEach((el) => el.classList.toggle('media-box__header--unselected')); - $$('.media-box__header').forEach((el) => el.classList.remove('media-box__header--selected')); - currentQueue().forEach((id) => - $$(`.media-box__header[data-image-id="${id}"]`).forEach((el) => el.classList.add('media-box__header--selected')), + $$('.media-box__header').forEach(el => el.classList.toggle('media-box__header--unselected')); + $$('.media-box__header').forEach(el => el.classList.remove('media-box__header--selected')); + currentQueue().forEach(id => + $$(`.media-box__header[data-image-id="${id}"]`).forEach(el => el.classList.add('media-box__header--selected')), ); } @@ -64,8 +64,8 @@ function submit() { image_ids: currentQueue(), }) .then(handleError) - .then((r) => r.json()) - .then((data) => { + .then(r => r.json()) + .then(data => { if (data.failed.length) window.alert(`Failed to add tags to the images with these IDs: ${data.failed}`); reset(); @@ -80,7 +80,7 @@ function modifyImageQueue(mediaBox) { isSelected ? queue.splice(queue.indexOf(imageId), 1) : queue.push(imageId); - $$(`.media-box__header[data-image-id="${imageId}"]`).forEach((el) => + $$(`.media-box__header[data-image-id="${imageId}"]`).forEach(el => el.classList.toggle('media-box__header--selected'), ); diff --git a/assets/js/search.ts b/assets/js/search.ts index 351105ea..269497d2 100644 --- a/assets/js/search.ts +++ b/assets/js/search.ts @@ -2,7 +2,7 @@ import { $, $$ } from './utils/dom'; import { addTag } from './tagsinput'; function showHelp(subject: string, type: string | null) { - $$('[data-search-help]').forEach((helpBox) => { + $$('[data-search-help]').forEach(helpBox => { if (helpBox.getAttribute('data-search-help') === type) { const searchSubject = $('.js-search-help-subject', helpBox); diff --git a/assets/js/settings.ts b/assets/js/settings.ts index ed4256b4..f40fa439 100644 --- a/assets/js/settings.ts +++ b/assets/js/settings.ts @@ -18,7 +18,7 @@ export function setupSettings() { const styleSheet = assertNotNull($('#js-theme-stylesheet')); // Local settings - localCheckboxes.forEach((checkbox) => { + localCheckboxes.forEach(checkbox => { checkbox.addEventListener('change', () => { store.set(checkbox.id.replace('user_', ''), checkbox.checked); }); diff --git a/assets/js/slider.ts b/assets/js/slider.ts index 95ca83fc..73edc488 100644 --- a/assets/js/slider.ts +++ b/assets/js/slider.ts @@ -169,7 +169,7 @@ function setupSlider(el: HTMLInputElement) { // Sets up all sliders currently on the page. function setupSliders() { - $$('input[type="dualrange"]').forEach((el) => { + $$('input[type="dualrange"]').forEach(el => { setupSlider(el); }); } diff --git a/assets/js/sources.ts b/assets/js/sources.ts index 0a0aab18..b4bc51ec 100644 --- a/assets/js/sources.ts +++ b/assets/js/sources.ts @@ -19,7 +19,7 @@ export function imageSourcesCreator() { if (target.matches('#source-form')) { const sourceSauce = assertNotNull($('.js-sourcesauce')); - detail.text().then((text) => { + detail.text().then(text => { sourceSauce.outerHTML = text; setupInputs(); }); diff --git a/assets/js/staffhider.ts b/assets/js/staffhider.ts index 23aa3899..86741d78 100644 --- a/assets/js/staffhider.ts +++ b/assets/js/staffhider.ts @@ -8,6 +8,6 @@ import { $$, hideEl } from './utils/dom'; export function hideStaffTools() { if (window.booru.hideStaffTools === 'true') { - $$('.js-staff-action').forEach((el) => hideEl(el)); + $$('.js-staff-action').forEach(el => hideEl(el)); } } diff --git a/assets/js/tags.ts b/assets/js/tags.ts index 4e7f9191..deb3c7bd 100644 --- a/assets/js/tags.ts +++ b/assets/js/tags.ts @@ -82,7 +82,7 @@ function createTagDropdown(tag: HTMLSpanElement) { if (!userIsSignedIn) showEl(signIn); if (userIsSignedIn && !userCanEditFilter) showEl(filter); - tag.addEventListener('fetchcomplete', (event) => { + tag.addEventListener('fetchcomplete', event => { const act = assertNotUndefined(event.target.dataset.tagAction); actions[act](); }); diff --git a/assets/js/tagsinput.js b/assets/js/tagsinput.js index 10e9fd61..bc05b3d7 100644 --- a/assets/js/tagsinput.js +++ b/assets/js/tagsinput.js @@ -81,7 +81,7 @@ function setupTagsInput(tagBlock) { // enter or comma if (keyCode === 13 || (keyCode === 188 && !shiftKey)) { event.preventDefault(); - inputField.value.split(',').forEach((t) => insertTag(t)); + inputField.value.split(',').forEach(t => insertTag(t)); inputField.value = ''; } } @@ -129,7 +129,7 @@ function setupTagsInput(tagBlock) { container.appendChild(inputField); tags = []; - textarea.value.split(',').forEach((t) => insertTag(t)); + textarea.value.split(',').forEach(t => insertTag(t)); textarea.value = tags.join(', '); } } @@ -143,7 +143,7 @@ function fancyEditorRequested(tagBlock) { } function setupTagListener() { - document.addEventListener('addtag', (event) => { + document.addEventListener('addtag', event => { if (event.target.value) event.target.value += ', '; event.target.value += event.detail.name; }); diff --git a/assets/js/tagsmisc.ts b/assets/js/tagsmisc.ts index acf65702..17fdf6d3 100644 --- a/assets/js/tagsmisc.ts +++ b/assets/js/tagsmisc.ts @@ -38,7 +38,7 @@ function tagInputButtons(event: MouseEvent) { } function setupTags() { - $$('.js-tag-block').forEach((el) => { + $$('.js-tag-block').forEach(el => { setupTagsInput(el); el.classList.remove('js-tag-block'); }); @@ -48,7 +48,7 @@ function updateTagSauce({ target, detail }: FetchcompleteEvent) { if (target.matches('#tags-form')) { const tagSauce = assertNotNull($('.js-tagsauce')); - detail.text().then((text) => { + detail.text().then(text => { tagSauce.outerHTML = text; setupTags(); initTagDropdown(); diff --git a/assets/js/ujs.ts b/assets/js/ujs.ts index 626f8c99..b2905806 100644 --- a/assets/js/ujs.ts +++ b/assets/js/ujs.ts @@ -57,7 +57,7 @@ function formRemote(event: Event, target: HTMLFormElement) { method: (target.dataset.method || target.method).toUpperCase(), headers: headers(), body: new FormData(target), - }).then((response) => { + }).then(response => { fire(target, 'fetchcomplete', response); if (response && response.status === 300) { window.location.reload(); @@ -66,7 +66,7 @@ function formRemote(event: Event, target: HTMLFormElement) { } function formReset(_event: Event | null, target: HTMLElement) { - $$('[disabled][data-disable-with][data-enable-with]', target).forEach((input) => { + $$('[disabled][data-disable-with][data-enable-with]', target).forEach(input => { const label = findFirstTextNode(input); if (label) { label.nodeValue = ` ${input.dataset.enableWith}`; @@ -85,7 +85,7 @@ function linkRemote(event: Event, target: HTMLAnchorElement) { credentials: 'same-origin', method: (target.dataset.method || 'get').toUpperCase(), headers: headers(), - }).then((response) => fire(target, 'fetchcomplete', response)); + }).then(response => fire(target, 'fetchcomplete', response)); } delegate(document, 'click', { diff --git a/assets/js/upload.js b/assets/js/upload.js index 6d0e52b5..16d33959 100644 --- a/assets/js/upload.js +++ b/assets/js/upload.js @@ -11,7 +11,7 @@ const MATROSKA_MAGIC = 0x1a45dfa3; function scrapeUrl(url) { return fetchJson('POST', '/images/scrape', { url }) .then(handleError) - .then((response) => response.json()); + .then(response => response.json()); } function elementForEmbeddedImage({ camo_url, type }) { @@ -34,7 +34,7 @@ function setupImageUpload() { const [fileField, remoteUrl, scraperError] = $$('.js-scraper', form); const descrEl = $('.js-image-descr-input', form); const tagsEl = $('.js-image-tags-input', form); - const sourceEl = $$('.js-source-url', form).find((input) => input.value === ''); + const sourceEl = $$('.js-source-url', form).find(input => input.value === ''); const fetchButton = $('#js-scraper-preview'); if (!fetchButton) return; @@ -80,7 +80,7 @@ function setupImageUpload() { const reader = new FileReader(); - reader.addEventListener('load', (event) => { + reader.addEventListener('load', event => { showImages([ { camo_url: event.target.result, @@ -107,7 +107,7 @@ function setupImageUpload() { disableFetch(); scrapeUrl(remoteUrl.value) - .then((data) => { + .then(data => { if (data === null) { scraperError.innerText = 'No image found at that address.'; showError(); @@ -136,7 +136,7 @@ function setupImageUpload() { }); // Fetch on "enter" in url field - remoteUrl.addEventListener('keydown', (event) => { + remoteUrl.addEventListener('keydown', event => { if (event.keyCode === 13) { // Hit enter fetchButton.click(); diff --git a/assets/js/utils/__tests__/draggable.spec.ts b/assets/js/utils/__tests__/draggable.spec.ts index d5415c23..7f9357a0 100644 --- a/assets/js/utils/__tests__/draggable.spec.ts +++ b/assets/js/utils/__tests__/draggable.spec.ts @@ -80,7 +80,7 @@ describe('Draggable Utilities', () => { expect(dataTransferItem.type).toEqual('text/plain'); let stringValue: string | undefined; - dataTransferItem.getAsString((value) => { + dataTransferItem.getAsString(value => { stringValue = value; }); expect(stringValue).toEqual(''); diff --git a/assets/js/utils/__tests__/events.spec.ts b/assets/js/utils/__tests__/events.spec.ts index 8c068e5b..575883b7 100644 --- a/assets/js/utils/__tests__/events.spec.ts +++ b/assets/js/utils/__tests__/events.spec.ts @@ -60,7 +60,7 @@ describe('Event utils', () => { const mockButton = document.createElement('button'); const mockHandler = vi.fn(); - mockButton.addEventListener('click', (e) => leftClick(mockHandler)(e, mockButton)); + mockButton.addEventListener('click', e => leftClick(mockHandler)(e, mockButton)); fireEvent.click(mockButton, { button: 0 }); @@ -72,7 +72,7 @@ describe('Event utils', () => { const mockHandler = vi.fn(); const mockButtonNumber = getRandomArrayItem([1, 2, 3, 4, 5]); - mockButton.addEventListener('click', (e) => leftClick(mockHandler)(e, mockButton)); + mockButton.addEventListener('click', e => leftClick(mockHandler)(e, mockButton)); fireEvent.click(mockButton, { button: mockButtonNumber }); diff --git a/assets/js/utils/__tests__/image.spec.ts b/assets/js/utils/__tests__/image.spec.ts index 8c3286f5..ded1389b 100644 --- a/assets/js/utils/__tests__/image.spec.ts +++ b/assets/js/utils/__tests__/image.spec.ts @@ -101,7 +101,7 @@ describe('Image utils', () => { const mockImage = new Image(); mockImage.src = mockImageUri; if (imgClasses) { - imgClasses.forEach((videoClass) => { + imgClasses.forEach(videoClass => { mockImage.classList.add(videoClass); }); } @@ -109,7 +109,7 @@ describe('Image utils', () => { const mockVideo = document.createElement('video'); if (videoClasses) { - videoClasses.forEach((videoClass) => { + videoClasses.forEach(videoClass => { mockVideo.classList.add(videoClass); }); } @@ -161,7 +161,7 @@ describe('Image utils', () => { expect(result).toBe(true); }); - ['data-size', 'data-uris'].forEach((missingAttributeName) => { + ['data-size', 'data-uris'].forEach(missingAttributeName => { it(`should return early if the ${missingAttributeName} attribute is missing`, () => { const { mockElement } = createMockElements({ extension: 'webm', diff --git a/assets/js/utils/dom.ts b/assets/js/utils/dom.ts index 12114b9b..48546122 100644 --- a/assets/js/utils/dom.ts +++ b/assets/js/utils/dom.ts @@ -25,37 +25,37 @@ export function $$( } export function showEl(...elements: E[] | ConcatArray[]) { - ([] as E[]).concat(...elements).forEach((el) => el.classList.remove('hidden')); + ([] as E[]).concat(...elements).forEach(el => el.classList.remove('hidden')); } export function hideEl(...elements: E[] | ConcatArray[]) { - ([] as E[]).concat(...elements).forEach((el) => el.classList.add('hidden')); + ([] as E[]).concat(...elements).forEach(el => el.classList.add('hidden')); } export function toggleEl(...elements: E[] | ConcatArray[]) { - ([] as E[]).concat(...elements).forEach((el) => el.classList.toggle('hidden')); + ([] as E[]).concat(...elements).forEach(el => el.classList.toggle('hidden')); } export function clearEl(...elements: E[] | ConcatArray[]) { - ([] as E[]).concat(...elements).forEach((el) => { + ([] as E[]).concat(...elements).forEach(el => { while (el.firstChild) el.removeChild(el.firstChild); }); } export function disableEl(...elements: E[] | ConcatArray[]) { - ([] as E[]).concat(...elements).forEach((el) => { + ([] as E[]).concat(...elements).forEach(el => { el.disabled = true; }); } export function enableEl(...elements: E[] | ConcatArray[]) { - ([] as E[]).concat(...elements).forEach((el) => { + ([] as E[]).concat(...elements).forEach(el => { el.disabled = false; }); } export function removeEl(...elements: E[] | ConcatArray[]) { - ([] as E[]).concat(...elements).forEach((el) => el.parentNode?.removeChild(el)); + ([] as E[]).concat(...elements).forEach(el => el.parentNode?.removeChild(el)); } export function makeEl( @@ -78,7 +78,7 @@ export function onLeftClick( callback: (e: MouseEvent) => boolean | void, context: Pick = document, ): VoidFunction { - const handler: typeof callback = (event) => { + const handler: typeof callback = event => { if (event.button === 0) callback(event); }; context.addEventListener('click', handler); @@ -106,5 +106,5 @@ export function escapeCss(css: string): string { } export function findFirstTextNode(of: Node): N { - return Array.prototype.filter.call(of.childNodes, (el) => el.nodeType === Node.TEXT_NODE)[0]; + return Array.prototype.filter.call(of.childNodes, el => el.nodeType === Node.TEXT_NODE)[0]; } diff --git a/assets/js/utils/draggable.ts b/assets/js/utils/draggable.ts index 69c5a9d3..72706648 100644 --- a/assets/js/utils/draggable.ts +++ b/assets/js/utils/draggable.ts @@ -56,7 +56,7 @@ function dragEnd(event: DragEvent, target: HTMLElement) { clearDragSource(); if (target.parentNode) { - $$('.over', target.parentNode).forEach((t) => t.classList.remove('over')); + $$('.over', target.parentNode).forEach(t => t.classList.remove('over')); } } diff --git a/assets/js/utils/events.ts b/assets/js/utils/events.ts index 06733721..70460bf8 100644 --- a/assets/js/utils/events.ts +++ b/assets/js/utils/events.ts @@ -48,7 +48,7 @@ export function delegate void | boolean>, ) { - node.addEventListener(event, (e) => { + node.addEventListener(event, e => { for (const selector in selectors) { const evtTarget = e.target as EventTarget | Target | null; if (evtTarget && 'closest' in evtTarget && typeof evtTarget.closest === 'function') { diff --git a/assets/js/utils/image.ts b/assets/js/utils/image.ts index cbdbb20e..da23f2ea 100644 --- a/assets/js/utils/image.ts +++ b/assets/js/utils/image.ts @@ -117,7 +117,7 @@ export function spoilerThumb(img: HTMLDivElement, spoilerUri: string, reason: st switch (window.booru.spoilerType) { case 'click': - img.addEventListener('click', (event) => { + img.addEventListener('click', event => { if (showThumb(img)) event.preventDefault(); }); img.addEventListener('mouseleave', () => hideThumb(img, spoilerUri, reason)); diff --git a/assets/js/utils/local-autocompleter.ts b/assets/js/utils/local-autocompleter.ts index f27f8e2d..ec3ba162 100644 --- a/assets/js/utils/local-autocompleter.ts +++ b/assets/js/utils/local-autocompleter.ts @@ -133,7 +133,7 @@ export class LocalAutocompleter { } // Add if not filtering or no associations are filtered - if (unfilter || hiddenTags.findIndex((ht) => result.associations.includes(ht)) === -1) { + if (unfilter || hiddenTags.findIndex(ht => result.associations.includes(ht)) === -1) { results[result.name] = result; } } diff --git a/assets/js/utils/tag.ts b/assets/js/utils/tag.ts index 7132efcb..fcd18d18 100644 --- a/assets/js/utils/tag.ts +++ b/assets/js/utils/tag.ts @@ -30,7 +30,7 @@ function sortTags(hidden: boolean, a: TagData, b: TagData): number { export function getHiddenTags(): TagData[] { return unique(window.booru.hiddenTagList) - .map((tagId) => getTag(tagId)) + .map(tagId => getTag(tagId)) .sort(sortTags.bind(null, true)); } @@ -38,8 +38,8 @@ export function getSpoileredTags(): TagData[] { if (window.booru.spoilerType === 'off') return []; return unique(window.booru.spoileredTagList) - .filter((tagId) => window.booru.ignoredTagList.indexOf(tagId) === -1) - .map((tagId) => getTag(tagId)) + .filter(tagId => window.booru.ignoredTagList.indexOf(tagId) === -1) + .map(tagId => getTag(tagId)) .sort(sortTags.bind(null, false)); } @@ -49,7 +49,7 @@ export function imageHitsTags(img: HTMLElement, matchTags: TagData[]): TagData[] return []; } const imageTags = JSON.parse(imageTagsString); - return matchTags.filter((t) => imageTags.indexOf(t.id) !== -1); + return matchTags.filter(t => imageTags.indexOf(t.id) !== -1); } export function imageHitsComplex(img: HTMLElement, matchComplex: AstMatcher) { @@ -63,7 +63,7 @@ export function displayTags(tags: TagData[]): string { extras; if (otherTags.length > 0) { - extras = otherTags.map((tag) => escapeHtml(tag.name)).join(', '); + extras = otherTags.map(tag => escapeHtml(tag.name)).join(', '); list += `, ${extras}`; } diff --git a/assets/test/mock-storage.ts b/assets/test/mock-storage.ts index c05bcda6..1f283f29 100644 --- a/assets/test/mock-storage.ts +++ b/assets/test/mock-storage.ts @@ -68,7 +68,7 @@ export function mockStorageImpl(): MockStorageImplApi { delete tempStorage[key]; }, }); - const forceStorageError: MockStorageImplApi['forceStorageError'] = (func) => { + const forceStorageError: MockStorageImplApi['forceStorageError'] = func => { shouldThrow = true; const value = func(); if (!(value instanceof Promise)) { @@ -80,7 +80,7 @@ export function mockStorageImpl(): MockStorageImplApi { shouldThrow = false; }); }; - const setStorageValue: MockStorageImplApi['setStorageValue'] = (value) => { + const setStorageValue: MockStorageImplApi['setStorageValue'] = value => { tempStorage = value; }; const clearStorage = () => setStorageValue({}); diff --git a/assets/vite.config.ts b/assets/vite.config.ts index 2eb4607d..812f7f8b 100644 --- a/assets/vite.config.ts +++ b/assets/vite.config.ts @@ -11,13 +11,13 @@ export default defineConfig(({ command, mode }: ConfigEnv): UserConfig => { const isDev = command !== 'build' && mode !== 'test'; const targets = new Map(); - fs.readdirSync(path.resolve(__dirname, 'css/themes/')).forEach((name) => { + fs.readdirSync(path.resolve(__dirname, 'css/themes/')).forEach(name => { const m = name.match(/([-a-z]+).css/); if (m) targets.set(`css/${m[1]}`, `./css/themes/${m[1]}.css`); }); - fs.readdirSync(path.resolve(__dirname, 'css/options/')).forEach((name) => { + fs.readdirSync(path.resolve(__dirname, 'css/options/')).forEach(name => { const m = name.match(/([-a-z]+).css/); if (m) targets.set(`css/options/${m[1]}`, `./css/options/${m[1]}.css`);