From f35e2b0cd1aaee389e4efda5a54976520b9bd4cb Mon Sep 17 00:00:00 2001 From: silverwind Date: Mon, 11 Nov 2024 12:13:57 +0100 Subject: [PATCH] Fix a number of typescript issues (#32459) Fixes 69 typescript errors found in the `admin` and `markup` folders. --------- Co-authored-by: Giteabot --- web_src/js/features/admin/common.ts | 105 +++++++++++++------------ web_src/js/features/admin/config.ts | 10 +-- web_src/js/features/admin/emails.ts | 7 +- web_src/js/features/admin/selfcheck.ts | 6 +- web_src/js/features/admin/users.ts | 12 +-- web_src/js/markup/anchors.ts | 20 ++--- web_src/js/markup/codecopy.ts | 4 +- web_src/js/markup/common.ts | 4 +- web_src/js/markup/content.ts | 4 +- web_src/js/markup/html2markdown.ts | 34 ++++---- web_src/js/markup/math.ts | 4 +- web_src/js/markup/mermaid.ts | 2 +- web_src/js/markup/tasklist.ts | 8 +- web_src/js/svg.ts | 2 +- 14 files changed, 109 insertions(+), 113 deletions(-) diff --git a/web_src/js/features/admin/common.ts b/web_src/js/features/admin/common.ts index 934a30a3ee..6c725a3efe 100644 --- a/web_src/js/features/admin/common.ts +++ b/web_src/js/features/admin/common.ts @@ -5,15 +5,15 @@ import {POST} from '../../modules/fetch.ts'; const {appSubUrl} = window.config; -function onSecurityProtocolChange() { - if (Number(document.querySelector('#security_protocol')?.value) > 0) { +function onSecurityProtocolChange(): void { + if (Number(document.querySelector('#security_protocol')?.value) > 0) { showElem('.has-tls'); } else { hideElem('.has-tls'); } } -export function initAdminCommon() { +export function initAdminCommon(): void { if (!document.querySelector('.page-content.admin')) return; // check whether appUrl(ROOT_URL) is correct, if not, show an error message @@ -21,34 +21,34 @@ export function initAdminCommon() { // New user if ($('.admin.new.user').length > 0 || $('.admin.edit.user').length > 0) { - document.querySelector('#login_type')?.addEventListener('change', function () { - if (this.value?.substring(0, 1) === '0') { - document.querySelector('#user_name')?.removeAttribute('disabled'); - document.querySelector('#login_name')?.removeAttribute('required'); + document.querySelector('#login_type')?.addEventListener('change', function () { + if (this.value?.startsWith('0')) { + document.querySelector('#user_name')?.removeAttribute('disabled'); + document.querySelector('#login_name')?.removeAttribute('required'); hideElem('.non-local'); showElem('.local'); - document.querySelector('#user_name')?.focus(); + document.querySelector('#user_name')?.focus(); if (this.getAttribute('data-password') === 'required') { document.querySelector('#password')?.setAttribute('required', 'required'); } } else { - if (document.querySelector('.admin.edit.user')) { - document.querySelector('#user_name')?.setAttribute('disabled', 'disabled'); + if (document.querySelector('.admin.edit.user')) { + document.querySelector('#user_name')?.setAttribute('disabled', 'disabled'); } - document.querySelector('#login_name')?.setAttribute('required', 'required'); + document.querySelector('#login_name')?.setAttribute('required', 'required'); showElem('.non-local'); hideElem('.local'); - document.querySelector('#login_name')?.focus(); + document.querySelector('#login_name')?.focus(); - document.querySelector('#password')?.removeAttribute('required'); + document.querySelector('#password')?.removeAttribute('required'); } }); } function onUsePagedSearchChange() { - const searchPageSizeElements = document.querySelectorAll('.search-page-size'); - if (document.querySelector('#use_paged_search').checked) { + const searchPageSizeElements = document.querySelectorAll('.search-page-size'); + if (document.querySelector('#use_paged_search').checked) { showElem('.search-page-size'); for (const el of searchPageSizeElements) { el.querySelector('input')?.setAttribute('required', 'required'); @@ -61,20 +61,20 @@ export function initAdminCommon() { } } - function onOAuth2Change(applyDefaultValues) { + function onOAuth2Change(applyDefaultValues: boolean) { hideElem('.open_id_connect_auto_discovery_url, .oauth2_use_custom_url'); - for (const input of document.querySelectorAll('.open_id_connect_auto_discovery_url input[required]')) { + for (const input of document.querySelectorAll('.open_id_connect_auto_discovery_url input[required]')) { input.removeAttribute('required'); } - const provider = document.querySelector('#oauth2_provider').value; + const provider = document.querySelector('#oauth2_provider').value; switch (provider) { case 'openidConnect': - document.querySelector('.open_id_connect_auto_discovery_url input').setAttribute('required', 'required'); + document.querySelector('.open_id_connect_auto_discovery_url input').setAttribute('required', 'required'); showElem('.open_id_connect_auto_discovery_url'); break; default: { - const elProviderCustomUrlSettings = document.querySelector(`#${provider}_customURLSettings`); + const elProviderCustomUrlSettings = document.querySelector(`#${provider}_customURLSettings`); if (!elProviderCustomUrlSettings) break; // some providers do not have custom URL settings const couldChangeCustomURLs = elProviderCustomUrlSettings.getAttribute('data-available') === 'true'; const mustProvideCustomURLs = elProviderCustomUrlSettings.getAttribute('data-required') === 'true'; @@ -82,7 +82,7 @@ export function initAdminCommon() { showElem('.oauth2_use_custom_url'); // show the checkbox } if (mustProvideCustomURLs) { - document.querySelector('#oauth2_use_custom_url').checked = true; // make the checkbox checked + document.querySelector('#oauth2_use_custom_url').checked = true; // make the checkbox checked } break; } @@ -91,17 +91,17 @@ export function initAdminCommon() { } function onOAuth2UseCustomURLChange(applyDefaultValues) { - const provider = document.querySelector('#oauth2_provider').value; + const provider = document.querySelector('#oauth2_provider').value; hideElem('.oauth2_use_custom_url_field'); - for (const input of document.querySelectorAll('.oauth2_use_custom_url_field input[required]')) { + for (const input of document.querySelectorAll('.oauth2_use_custom_url_field input[required]')) { input.removeAttribute('required'); } const elProviderCustomUrlSettings = document.querySelector(`#${provider}_customURLSettings`); - if (elProviderCustomUrlSettings && document.querySelector('#oauth2_use_custom_url').checked) { + if (elProviderCustomUrlSettings && document.querySelector('#oauth2_use_custom_url').checked) { for (const custom of ['token_url', 'auth_url', 'profile_url', 'email_url', 'tenant']) { if (applyDefaultValues) { - document.querySelector(`#oauth2_${custom}`).value = document.querySelector(`#${provider}_${custom}`).value; + document.querySelector(`#oauth2_${custom}`).value = document.querySelector(`#${provider}_${custom}`).value; } const customInput = document.querySelector(`#${provider}_${custom}`); if (customInput && customInput.getAttribute('data-available') === 'true') { @@ -115,25 +115,26 @@ export function initAdminCommon() { } function onEnableLdapGroupsChange() { - toggleElem(document.querySelector('#ldap-group-options'), $('.js-ldap-group-toggle')[0].checked); + const checked = document.querySelector('.js-ldap-group-toggle')?.checked; + toggleElem(document.querySelector('#ldap-group-options'), checked); } // New authentication - if (document.querySelector('.admin.new.authentication')) { - document.querySelector('#auth_type')?.addEventListener('change', function () { + if (document.querySelector('.admin.new.authentication')) { + document.querySelector('#auth_type')?.addEventListener('change', function () { hideElem('.ldap, .dldap, .smtp, .pam, .oauth2, .has-tls, .search-page-size, .sspi'); - for (const input of document.querySelectorAll('.ldap input[required], .binddnrequired input[required], .dldap input[required], .smtp input[required], .pam input[required], .oauth2 input[required], .has-tls input[required], .sspi input[required]')) { + for (const input of document.querySelectorAll('.ldap input[required], .binddnrequired input[required], .dldap input[required], .smtp input[required], .pam input[required], .oauth2 input[required], .has-tls input[required], .sspi input[required]')) { input.removeAttribute('required'); } - document.querySelector('.binddnrequired')?.classList.remove('required'); + document.querySelector('.binddnrequired')?.classList.remove('required'); const authType = this.value; switch (authType) { case '2': // LDAP showElem('.ldap'); - for (const input of document.querySelectorAll('.binddnrequired input, .ldap div.required:not(.dldap) input')) { + for (const input of document.querySelectorAll('.binddnrequired input, .ldap div.required:not(.dldap) input')) { input.setAttribute('required', 'required'); } document.querySelector('.binddnrequired')?.classList.add('required'); @@ -141,32 +142,32 @@ export function initAdminCommon() { case '3': // SMTP showElem('.smtp'); showElem('.has-tls'); - for (const input of document.querySelectorAll('.smtp div.required input, .has-tls')) { + for (const input of document.querySelectorAll('.smtp div.required input, .has-tls')) { input.setAttribute('required', 'required'); } break; case '4': // PAM showElem('.pam'); - for (const input of document.querySelectorAll('.pam input')) { + for (const input of document.querySelectorAll('.pam input')) { input.setAttribute('required', 'required'); } break; case '5': // LDAP showElem('.dldap'); - for (const input of document.querySelectorAll('.dldap div.required:not(.ldap) input')) { + for (const input of document.querySelectorAll('.dldap div.required:not(.ldap) input')) { input.setAttribute('required', 'required'); } break; case '6': // OAuth2 showElem('.oauth2'); - for (const input of document.querySelectorAll('.oauth2 div.required:not(.oauth2_use_custom_url,.oauth2_use_custom_url_field,.open_id_connect_auto_discovery_url) input')) { + for (const input of document.querySelectorAll('.oauth2 div.required:not(.oauth2_use_custom_url,.oauth2_use_custom_url_field,.open_id_connect_auto_discovery_url) input')) { input.setAttribute('required', 'required'); } onOAuth2Change(true); break; case '7': // SSPI showElem('.sspi'); - for (const input of document.querySelectorAll('.sspi div.required input')) { + for (const input of document.querySelectorAll('.sspi div.required input')) { input.setAttribute('required', 'required'); } break; @@ -180,39 +181,39 @@ export function initAdminCommon() { } }); $('#auth_type').trigger('change'); - document.querySelector('#security_protocol')?.addEventListener('change', onSecurityProtocolChange); - document.querySelector('#use_paged_search')?.addEventListener('change', onUsePagedSearchChange); - document.querySelector('#oauth2_provider')?.addEventListener('change', () => onOAuth2Change(true)); - document.querySelector('#oauth2_use_custom_url')?.addEventListener('change', () => onOAuth2UseCustomURLChange(true)); + document.querySelector('#security_protocol')?.addEventListener('change', onSecurityProtocolChange); + document.querySelector('#use_paged_search')?.addEventListener('change', onUsePagedSearchChange); + document.querySelector('#oauth2_provider')?.addEventListener('change', () => onOAuth2Change(true)); + document.querySelector('#oauth2_use_custom_url')?.addEventListener('change', () => onOAuth2UseCustomURLChange(true)); $('.js-ldap-group-toggle').on('change', onEnableLdapGroupsChange); } // Edit authentication - if (document.querySelector('.admin.edit.authentication')) { - const authType = document.querySelector('#auth_type')?.value; + if (document.querySelector('.admin.edit.authentication')) { + const authType = document.querySelector('#auth_type')?.value; if (authType === '2' || authType === '5') { - document.querySelector('#security_protocol')?.addEventListener('change', onSecurityProtocolChange); + document.querySelector('#security_protocol')?.addEventListener('change', onSecurityProtocolChange); $('.js-ldap-group-toggle').on('change', onEnableLdapGroupsChange); onEnableLdapGroupsChange(); if (authType === '2') { - document.querySelector('#use_paged_search')?.addEventListener('change', onUsePagedSearchChange); + document.querySelector('#use_paged_search')?.addEventListener('change', onUsePagedSearchChange); } } else if (authType === '6') { - document.querySelector('#oauth2_provider')?.addEventListener('change', () => onOAuth2Change(true)); - document.querySelector('#oauth2_use_custom_url')?.addEventListener('change', () => onOAuth2UseCustomURLChange(false)); + document.querySelector('#oauth2_provider')?.addEventListener('change', () => onOAuth2Change(true)); + document.querySelector('#oauth2_use_custom_url')?.addEventListener('change', () => onOAuth2UseCustomURLChange(false)); onOAuth2Change(false); } } - if (document.querySelector('.admin.authentication')) { + if (document.querySelector('.admin.authentication')) { $('#auth_name').on('input', function () { // appSubUrl is either empty or is a path that starts with `/` and doesn't have a trailing slash. - document.querySelector('#oauth2-callback-url').textContent = `${window.location.origin}${appSubUrl}/user/oauth2/${encodeURIComponent(this.value)}/callback`; + document.querySelector('#oauth2-callback-url').textContent = `${window.location.origin}${appSubUrl}/user/oauth2/${encodeURIComponent((this as HTMLInputElement).value)}/callback`; }).trigger('input'); } // Notice - if (document.querySelector('.admin.notice')) { - const detailModal = document.querySelector('#detail-modal'); + if (document.querySelector('.admin.notice')) { + const detailModal = document.querySelector('#detail-modal'); // Attach view detail modals $('.view-detail').on('click', function () { @@ -223,7 +224,7 @@ export function initAdminCommon() { }); // Select actions - const checkboxes = document.querySelectorAll('.select.table .ui.checkbox input'); + const checkboxes = document.querySelectorAll('.select.table .ui.checkbox input'); $('.select.action').on('click', function () { switch ($(this).data('action')) { @@ -244,7 +245,7 @@ export function initAdminCommon() { break; } }); - document.querySelector('#delete-selection')?.addEventListener('click', async function (e) { + document.querySelector('#delete-selection')?.addEventListener('click', async function (e) { e.preventDefault(); this.classList.add('is-loading', 'disabled'); const data = new FormData(); diff --git a/web_src/js/features/admin/config.ts b/web_src/js/features/admin/config.ts index 0d130703ae..16d7a2426f 100644 --- a/web_src/js/features/admin/config.ts +++ b/web_src/js/features/admin/config.ts @@ -3,17 +3,17 @@ import {POST} from '../../modules/fetch.ts'; const {appSubUrl} = window.config; -export function initAdminConfigs() { - const elAdminConfig = document.querySelector('.page-content.admin.config'); +export function initAdminConfigs(): void { + const elAdminConfig = document.querySelector('.page-content.admin.config'); if (!elAdminConfig) return; - for (const el of elAdminConfig.querySelectorAll('input[type="checkbox"][data-config-dyn-key]')) { + for (const el of elAdminConfig.querySelectorAll('input[type="checkbox"][data-config-dyn-key]')) { el.addEventListener('change', async () => { try { const resp = await POST(`${appSubUrl}/-/admin/config`, { - data: new URLSearchParams({key: el.getAttribute('data-config-dyn-key'), value: el.checked}), + data: new URLSearchParams({key: el.getAttribute('data-config-dyn-key'), value: String(el.checked)}), }); - const json = await resp.json(); + const json: Record = await resp.json(); if (json.errorMessage) throw new Error(json.errorMessage); } catch (ex) { showTemporaryTooltip(el, ex.toString()); diff --git a/web_src/js/features/admin/emails.ts b/web_src/js/features/admin/emails.ts index 46fafa7eff..8e97b67bf9 100644 --- a/web_src/js/features/admin/emails.ts +++ b/web_src/js/features/admin/emails.ts @@ -1,7 +1,7 @@ import $ from 'jquery'; -export function initAdminEmails() { - function linkEmailAction(e) { +export function initAdminEmails(): void { + $('.link-email-action').on('click', (e) => { const $this = $(this); $('#form-uid').val($this.data('uid')); $('#form-email').val($this.data('email')); @@ -9,6 +9,5 @@ export function initAdminEmails() { $('#form-activate').val($this.data('activate')); $('#change-email-modal').modal('show'); e.preventDefault(); - } - $('.link-email-action').on('click', linkEmailAction); + }); } diff --git a/web_src/js/features/admin/selfcheck.ts b/web_src/js/features/admin/selfcheck.ts index 925a50130f..9f53378b52 100644 --- a/web_src/js/features/admin/selfcheck.ts +++ b/web_src/js/features/admin/selfcheck.ts @@ -7,16 +7,16 @@ export async function initAdminSelfCheck() { const elCheckByFrontend = document.querySelector('#self-check-by-frontend'); if (!elCheckByFrontend) return; - const elContent = document.querySelector('.page-content.admin .admin-setting-content'); + const elContent = document.querySelector('.page-content.admin .admin-setting-content'); // send frontend self-check request const resp = await POST(`${appSubUrl}/-/admin/self_check`, { data: new URLSearchParams({ location_origin: window.location.origin, - now: Date.now(), // TODO: check time difference between server and client + now: String(Date.now()), // TODO: check time difference between server and client }), }); - const json = await resp.json(); + const json: Record = await resp.json(); toggleElem(elCheckByFrontend, Boolean(json.problems?.length)); for (const problem of json.problems ?? []) { const elProblem = document.createElement('div'); diff --git a/web_src/js/features/admin/users.ts b/web_src/js/features/admin/users.ts index 7cac603b5c..16276773e1 100644 --- a/web_src/js/features/admin/users.ts +++ b/web_src/js/features/admin/users.ts @@ -1,8 +1,8 @@ -export function initAdminUserListSearchForm() { +export function initAdminUserListSearchForm(): void { const searchForm = window.config.pageData.adminUserListSearchForm; if (!searchForm) return; - const form = document.querySelector('#user-list-search-form'); + const form = document.querySelector('#user-list-search-form'); if (!form) return; for (const button of form.querySelectorAll(`button[name=sort][value="${searchForm.SortType}"]`)) { @@ -12,23 +12,23 @@ export function initAdminUserListSearchForm() { if (searchForm.StatusFilterMap) { for (const [k, v] of Object.entries(searchForm.StatusFilterMap)) { if (!v) continue; - for (const input of form.querySelectorAll(`input[name="status_filter[${k}]"][value="${v}"]`)) { + for (const input of form.querySelectorAll(`input[name="status_filter[${k}]"][value="${v}"]`)) { input.checked = true; } } } - for (const radio of form.querySelectorAll('input[type=radio]')) { + for (const radio of form.querySelectorAll('input[type=radio]')) { radio.addEventListener('click', () => { form.submit(); }); } - const resetButtons = form.querySelectorAll('.j-reset-status-filter'); + const resetButtons = form.querySelectorAll('.j-reset-status-filter'); for (const button of resetButtons) { button.addEventListener('click', (e) => { e.preventDefault(); - for (const input of form.querySelectorAll('input[type=radio]')) { + for (const input of form.querySelectorAll('input[type=radio]')) { if (input.name.startsWith('status_filter[')) { input.checked = false; } diff --git a/web_src/js/markup/anchors.ts b/web_src/js/markup/anchors.ts index 8f0a88f130..483d72bd5b 100644 --- a/web_src/js/markup/anchors.ts +++ b/web_src/js/markup/anchors.ts @@ -1,11 +1,11 @@ import {svg} from '../svg.ts'; -const addPrefix = (str) => `user-content-${str}`; -const removePrefix = (str) => str.replace(/^user-content-/, ''); -const hasPrefix = (str) => str.startsWith('user-content-'); +const addPrefix = (str: string): string => `user-content-${str}`; +const removePrefix = (str: string): string => str.replace(/^user-content-/, ''); +const hasPrefix = (str: string): boolean => str.startsWith('user-content-'); // scroll to anchor while respecting the `user-content` prefix that exists on the target -function scrollToAnchor(encodedId) { +function scrollToAnchor(encodedId: string): void { if (!encodedId) return; const id = decodeURIComponent(encodedId); const prefixedId = addPrefix(id); @@ -24,7 +24,7 @@ function scrollToAnchor(encodedId) { el?.scrollIntoView(); } -export function initMarkupAnchors() { +export function initMarkupAnchors(): void { const markupEls = document.querySelectorAll('.markup'); if (!markupEls.length) return; @@ -39,7 +39,7 @@ export function initMarkupAnchors() { } // remove `user-content-` prefix from links so they don't show in url bar when clicked - for (const a of markupEl.querySelectorAll('a[href^="#"]')) { + for (const a of markupEl.querySelectorAll('a[href^="#"]')) { const href = a.getAttribute('href'); if (!href.startsWith('#user-content-')) continue; a.setAttribute('href', `#${removePrefix(href.substring(1))}`); @@ -47,15 +47,15 @@ export function initMarkupAnchors() { // add `user-content-` prefix to user-generated `a[name]` link targets // TODO: this prefix should be added in backend instead - for (const a of markupEl.querySelectorAll('a[name]')) { + for (const a of markupEl.querySelectorAll('a[name]')) { const name = a.getAttribute('name'); if (!name) continue; - a.setAttribute('name', addPrefix(a.name)); + a.setAttribute('name', addPrefix(name)); } - for (const a of markupEl.querySelectorAll('a[href^="#"]')) { + for (const a of markupEl.querySelectorAll('a[href^="#"]')) { a.addEventListener('click', (e) => { - scrollToAnchor(e.currentTarget.getAttribute('href')?.substring(1)); + scrollToAnchor((e.currentTarget as HTMLAnchorElement).getAttribute('href')?.substring(1)); }); } } diff --git a/web_src/js/markup/codecopy.ts b/web_src/js/markup/codecopy.ts index 0fac4a0a39..f45b7a8e04 100644 --- a/web_src/js/markup/codecopy.ts +++ b/web_src/js/markup/codecopy.ts @@ -1,13 +1,13 @@ import {svg} from '../svg.ts'; -export function makeCodeCopyButton() { +export function makeCodeCopyButton(): HTMLButtonElement { const button = document.createElement('button'); button.classList.add('code-copy', 'ui', 'button'); button.innerHTML = svg('octicon-copy'); return button; } -export function renderCodeCopy() { +export function renderCodeCopy(): void { const els = document.querySelectorAll('.markup .code-block code'); if (!els.length) return; diff --git a/web_src/js/markup/common.ts b/web_src/js/markup/common.ts index aff4a32423..e826c8fd86 100644 --- a/web_src/js/markup/common.ts +++ b/web_src/js/markup/common.ts @@ -1,8 +1,8 @@ -export function displayError(el, err) { +export function displayError(el: Element, err: Error): void { el.classList.remove('is-loading'); const errorNode = document.createElement('pre'); errorNode.setAttribute('class', 'ui message error markup-block-error'); - errorNode.textContent = err.str || err.message || String(err); + errorNode.textContent = err.message || String(err); el.before(errorNode); el.setAttribute('data-render-done', 'true'); } diff --git a/web_src/js/markup/content.ts b/web_src/js/markup/content.ts index e7f7b7f0c4..b9190b15ce 100644 --- a/web_src/js/markup/content.ts +++ b/web_src/js/markup/content.ts @@ -5,7 +5,7 @@ import {renderAsciicast} from './asciicast.ts'; import {initMarkupTasklist} from './tasklist.ts'; // code that runs for all markup content -export function initMarkupContent() { +export function initMarkupContent(): void { renderMermaid(); renderMath(); renderCodeCopy(); @@ -13,6 +13,6 @@ export function initMarkupContent() { } // code that only runs for comments -export function initCommentContent() { +export function initCommentContent(): void { initMarkupTasklist(); } diff --git a/web_src/js/markup/html2markdown.ts b/web_src/js/markup/html2markdown.ts index c690e0c8b1..3f7ef38002 100644 --- a/web_src/js/markup/html2markdown.ts +++ b/web_src/js/markup/html2markdown.ts @@ -12,21 +12,20 @@ type ProcessorContext = { function prepareProcessors(ctx:ProcessorContext): Processors { const processors = { - H1(el) { + H1(el: HTMLHeadingElement) { const level = parseInt(el.tagName.slice(1)); el.textContent = `${'#'.repeat(level)} ${el.textContent.trim()}`; }, - STRONG(el) { + STRONG(el: HTMLElement) { return `**${el.textContent}**`; }, - EM(el) { + EM(el: HTMLElement) { return `_${el.textContent}_`; }, - DEL(el) { + DEL(el: HTMLElement) { return `~~${el.textContent}~~`; }, - - A(el) { + A(el: HTMLAnchorElement) { const text = el.textContent || 'link'; const href = el.getAttribute('href'); if (/^https?:/.test(text) && text === href) { @@ -34,7 +33,7 @@ function prepareProcessors(ctx:ProcessorContext): Processors { } return href ? `[${text}](${href})` : text; }, - IMG(el) { + IMG(el: HTMLImageElement) { const alt = el.getAttribute('alt') || 'image'; const src = el.getAttribute('src'); const widthAttr = el.hasAttribute('width') ? ` width="${htmlEscape(el.getAttribute('width') || '')}"` : ''; @@ -44,32 +43,29 @@ function prepareProcessors(ctx:ProcessorContext): Processors { } return `![${alt}](${src})`; }, - - P(el) { + P(el: HTMLParagraphElement) { el.textContent = `${el.textContent}\n`; }, - BLOCKQUOTE(el) { + BLOCKQUOTE(el: HTMLElement) { el.textContent = `${el.textContent.replace(/^/mg, '> ')}\n`; }, - - OL(el) { + OL(el: HTMLElement) { const preNewLine = ctx.listNestingLevel ? '\n' : ''; el.textContent = `${preNewLine}${el.textContent}\n`; }, - LI(el) { + LI(el: HTMLElement) { const parent = el.parentNode; - const bullet = parent.tagName === 'OL' ? `1. ` : '* '; + const bullet = (parent as HTMLElement).tagName === 'OL' ? `1. ` : '* '; const nestingIdentLevel = Math.max(0, ctx.listNestingLevel - 1); el.textContent = `${' '.repeat(nestingIdentLevel * 4)}${bullet}${el.textContent}${ctx.elementIsLast ? '' : '\n'}`; return el; }, - INPUT(el) { + INPUT(el: HTMLInputElement) { return el.checked ? '[x] ' : '[ ] '; }, - - CODE(el) { + CODE(el: HTMLElement) { const text = el.textContent; - if (el.parentNode && el.parentNode.tagName === 'PRE') { + if (el.parentNode && (el.parentNode as HTMLElement).tagName === 'PRE') { el.textContent = `\`\`\`\n${text}\n\`\`\`\n`; return el; } @@ -86,7 +82,7 @@ function prepareProcessors(ctx:ProcessorContext): Processors { return processors; } -function processElement(ctx :ProcessorContext, processors: Processors, el: HTMLElement) { +function processElement(ctx :ProcessorContext, processors: Processors, el: HTMLElement): string | void { if (el.hasAttribute('data-markdown-generated-content')) return el.textContent; if (el.tagName === 'A' && el.children.length === 1 && el.children[0].tagName === 'IMG') { return processElement(ctx, processors, el.children[0] as HTMLElement); diff --git a/web_src/js/markup/math.ts b/web_src/js/markup/math.ts index e10d90fa2a..34ca79f493 100644 --- a/web_src/js/markup/math.ts +++ b/web_src/js/markup/math.ts @@ -1,12 +1,12 @@ import {displayError} from './common.ts'; -function targetElement(el) { +function targetElement(el: Element) { // The target element is either the current element if it has the // `is-loading` class or the pre that contains it return el.classList.contains('is-loading') ? el : el.closest('pre'); } -export async function renderMath() { +export async function renderMath(): void { const els = document.querySelectorAll('.markup code.language-math'); if (!els.length) return; diff --git a/web_src/js/markup/mermaid.ts b/web_src/js/markup/mermaid.ts index 5c27d6ca1c..004795d367 100644 --- a/web_src/js/markup/mermaid.ts +++ b/web_src/js/markup/mermaid.ts @@ -10,7 +10,7 @@ body {margin: 0; padding: 0; overflow: hidden} #mermaid {display: block; margin: 0 auto} blockquote, dd, dl, figure, h1, h2, h3, h4, h5, h6, hr, p, pre {margin: 0}`; -export async function renderMermaid() { +export async function renderMermaid(): Promise { const els = document.querySelectorAll('.markup code.language-mermaid'); if (!els.length) return; diff --git a/web_src/js/markup/tasklist.ts b/web_src/js/markup/tasklist.ts index 93896ccf07..95db7fc845 100644 --- a/web_src/js/markup/tasklist.ts +++ b/web_src/js/markup/tasklist.ts @@ -1,7 +1,7 @@ import {POST} from '../modules/fetch.ts'; import {showErrorToast} from '../modules/toast.ts'; -const preventListener = (e) => e.preventDefault(); +const preventListener = (e: Event) => e.preventDefault(); /** * Attaches `input` handlers to markdown rendered tasklist checkboxes in comments. @@ -10,10 +10,10 @@ const preventListener = (e) => e.preventDefault(); * is set accordingly and sent to the server. On success it updates the raw-content on * error it resets the checkbox to its original value. */ -export function initMarkupTasklist() { +export function initMarkupTasklist(): void { for (const el of document.querySelectorAll(`.markup[data-can-edit=true]`) || []) { const container = el.parentNode; - const checkboxes = el.querySelectorAll(`.task-list-item input[type=checkbox]`); + const checkboxes = el.querySelectorAll(`.task-list-item input[type=checkbox]`); for (const checkbox of checkboxes) { if (checkbox.hasAttribute('data-editable')) { @@ -52,7 +52,7 @@ export function initMarkupTasklist() { } try { - const editContentZone = container.querySelector('.edit-content-zone'); + const editContentZone = container.querySelector('.edit-content-zone'); const updateUrl = editContentZone.getAttribute('data-update-url'); const context = editContentZone.getAttribute('data-context'); const contentVersion = editContentZone.getAttribute('data-content-version'); diff --git a/web_src/js/svg.ts b/web_src/js/svg.ts index 6227a85e33..d04f63793f 100644 --- a/web_src/js/svg.ts +++ b/web_src/js/svg.ts @@ -153,7 +153,7 @@ export type SvgName = keyof typeof svgs; // most of the SVG icons in assets couldn't be used directly. // retrieve an HTML string for given SVG icon name, size and additional classes -export function svg(name: SvgName, size = 16, classNames: string|string[]): string { +export function svg(name: SvgName, size = 16, classNames?: string|string[]): string { const className = Array.isArray(classNames) ? classNames.join(' ') : classNames; if (!(name in svgs)) throw new Error(`Unknown SVG icon: ${name}`); if (size === 16 && !className) return svgs[name];