Skip to content

Commit 0df3bcc

Browse files
authored
Fix typescript errors and add CI check (#2170)
* Add ci check * Fix all typescript errors * Fix lint errors * Prettier
1 parent 1c8d00c commit 0df3bcc

File tree

16 files changed

+156
-102
lines changed

16 files changed

+156
-102
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ jobs:
9999

100100
- name: Format
101101
run: npm run fmt:check
102+
103+
- name: Compile
104+
run: npm run compile:check
102105

103106
- name: Build
104107
run: npm run build

src/Elastic.Documentation.Site/Assets/applies-switch.ts

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
// TODO: refactor to typescript. this was copied from the tabs implementation
2-
3-
// @ts-check
2+
import { $$ } from 'select-dom'
43

54
// Extra JS capability for selected applies switches to be synced
65
// The selection is stored in local storage so that it persists across page loads.
76

8-
const as_id_to_elements = {}
9-
const storageKeyPrefix = 'sphinx-design-applies-switch-id-'
7+
const as_id_to_elements: { [key: string]: HTMLElement[] } = {}
8+
const storageKeyPrefix = 'applies-switch-id-'
109

1110
function create_key(el: HTMLElement) {
1211
const syncId = el.getAttribute('data-sync-id')
@@ -22,16 +21,16 @@ function create_key(el: HTMLElement) {
2221
function ready() {
2322
// Find all applies switches with sync data
2423

25-
const groups = []
24+
const groups: string[] = []
2625

27-
document.querySelectorAll('.applies-switch-label').forEach((label) => {
26+
$$('.applies-switch-label').forEach((label) => {
2827
if (label instanceof HTMLElement) {
2928
const data = create_key(label)
3029
if (data) {
3130
const [group, id, key] = data
3231

3332
// add click event listener
34-
label.onclick = onAppliesSwitchLabelClick
33+
label.addEventListener('click', onAppliesSwitchLabelClick)
3534

3635
// store map of key to elements
3736
if (!as_id_to_elements[key]) {
@@ -72,13 +71,17 @@ function ready() {
7271
*
7372
* @this {HTMLElement} - The element that was clicked.
7473
*/
75-
function onAppliesSwitchLabelClick() {
74+
function onAppliesSwitchLabelClick(this: HTMLLabelElement) {
7675
const data = create_key(this)
7776
if (!data) return
7877
const [group, id, key] = data
7978
for (const label of as_id_to_elements[key]) {
80-
if (label === this) continue
81-
label.previousElementSibling.checked = true
79+
if (label === this) {
80+
continue
81+
}
82+
if (label.previousElementSibling instanceof HTMLInputElement) {
83+
label.previousElementSibling.checked = true
84+
}
8285
}
8386
window.sessionStorage.setItem(storageKeyPrefix + group, id)
8487
}

src/Elastic.Documentation.Site/Assets/copybutton.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
2+
// @ts-nocheck
3+
// This is copied from legacy. It works, but we should rework this if we ever need to change it
14
import { $$ } from 'select-dom'
25

36
const DOCUMENTATION_OPTIONS = {

src/Elastic.Documentation.Site/Assets/eui-icons-cache.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
2+
// @ts-nocheck: EUI icons do not have types
13
import { icon as EuiIconVisualizeApp } from '@elastic/eui/es/components/icon/assets/app_visualize'
24
import { icon as EuiIconArrowDown } from '@elastic/eui/es/components/icon/assets/arrow_down'
35
import { icon as EuiIconArrowLeft } from '@elastic/eui/es/components/icon/assets/arrow_left'
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
declare module '@elastic/highlightjs-esql' {
2+
import { LanguageFn } from 'highlight.js'
3+
const esql: LanguageFn
4+
export default esql
5+
}

src/Elastic.Documentation.Site/Assets/image-carousel.ts

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
import { $$ } from 'select-dom'
2+
13
class ImageCarousel {
24
private container: HTMLElement
3-
private slides: HTMLElement[]
4-
private indicators: HTMLElement[]
5-
private prevButton: HTMLElement | null
6-
private nextButton: HTMLElement | null
5+
private slides: HTMLElement[] = []
6+
private indicators: HTMLElement[] = []
7+
private prevButton: HTMLElement | null = null
8+
private nextButton: HTMLElement | null = null
79
private currentIndex: number = 0
810
private touchStartX: number = 0
911
private touchEndX: number = 0
@@ -245,9 +247,7 @@ export function initImageCarousel(): void {
245247
if (!section) return
246248

247249
// First, collect all images we want in the carousel
248-
const allImageLinks = Array.from(
249-
section.querySelectorAll('a[href*="epr.elastic.co"]')
250-
)
250+
const allImageLinks = $$('a[href*="epr.elastic.co"]', section)
251251

252252
// Track URLs to prevent duplicates
253253
const processedUrls = new Set()
@@ -329,7 +329,11 @@ export function initImageCarousel(): void {
329329
parent.style.display = 'none'
330330
break
331331
}
332-
parent = parent.parentElement
332+
333+
if (parent.parentElement) {
334+
parent = parent.parentElement
335+
}
336+
333337
maxAttempts--
334338
}
335339

@@ -397,9 +401,9 @@ export function initImageCarousel(): void {
397401

398402
// Helper to find a suitable container for an image
399403
function findClosestContainer(
400-
element: Element,
401-
carousel: Element
402-
): Element | null {
404+
element: HTMLElement,
405+
carousel: HTMLElement
406+
): HTMLElement | null {
403407
let current = element
404408
while (
405409
current &&

src/Elastic.Documentation.Site/Assets/main.ts

Lines changed: 77 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,17 @@ import { initTabs } from './tabs'
1010
import { initTocNav } from './toc-nav'
1111
import 'htmx-ext-head-support'
1212
import 'htmx-ext-preload'
13-
import katex from 'katex'
13+
import * as katex from 'katex'
1414
import { $, $$ } from 'select-dom'
1515
import { UAParser } from 'ua-parser-js'
1616

1717
const { getOS } = new UAParser()
1818
const isLazyLoadNavigationEnabled =
1919
$('meta[property="docs:feature:lazy-load-navigation"]')?.content === 'true'
2020

21+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
22+
type HtmxEvent = any
23+
2124
/**
2225
* Initialize KaTeX math rendering for elements with class 'math'
2326
*/
@@ -71,7 +74,7 @@ document.addEventListener('DOMContentLoaded', function () {
7174
initMath()
7275
})
7376

74-
document.addEventListener('htmx:load', function (event) {
77+
document.addEventListener('htmx:load', function (event: HtmxEvent) {
7578
initTocNav()
7679
initHighlight()
7780
initCopyButton()
@@ -99,14 +102,17 @@ document.addEventListener('htmx:load', function (event) {
99102
})
100103

101104
// Don't remove style tags because they are used by the elastic global nav.
102-
document.addEventListener('htmx:removingHeadElement', function (event) {
103-
const tagName = event.detail.headElement.tagName
104-
if (tagName === 'STYLE') {
105-
event.preventDefault()
105+
document.addEventListener(
106+
'htmx:removingHeadElement',
107+
function (event: HtmxEvent) {
108+
const tagName = event.detail.headElement.tagName
109+
if (tagName === 'STYLE') {
110+
event.preventDefault()
111+
}
106112
}
107-
})
113+
)
108114

109-
document.addEventListener('htmx:beforeRequest', function (event) {
115+
document.addEventListener('htmx:beforeRequest', function (event: HtmxEvent) {
110116
if (
111117
event.detail.requestConfig.verb === 'get' &&
112118
event.detail.requestConfig.triggeringEvent
@@ -126,60 +132,75 @@ document.addEventListener('htmx:beforeRequest', function (event) {
126132
}
127133
})
128134

129-
document.body.addEventListener('htmx:oobBeforeSwap', function (event) {
130-
// This is needed to scroll to the top of the page when the content is swapped
131-
if (
132-
event.target.id === 'main-container' ||
133-
event.target.id === 'markdown-content' ||
134-
event.target.id === 'content-container'
135-
) {
136-
window.scrollTo(0, 0)
135+
document.body.addEventListener(
136+
'htmx:oobBeforeSwap',
137+
function (event: HtmxEvent) {
138+
// This is needed to scroll to the top of the page when the content is swapped
139+
if (
140+
event.target?.id === 'main-container' ||
141+
event.target?.id === 'markdown-content' ||
142+
event.target?.id === 'content-container'
143+
) {
144+
window.scrollTo(0, 0)
145+
}
137146
}
138-
})
139-
140-
document.body.addEventListener('htmx:pushedIntoHistory', function (event) {
141-
const pagesNav = $('#pages-nav')
142-
const currentNavItem = $$('.current', pagesNav)
143-
currentNavItem.forEach((el) => {
144-
el.classList.remove('current')
145-
})
146-
const navItems = $$('a[href="' + event.detail.path + '"]', pagesNav)
147-
navItems.forEach((navItem) => {
148-
navItem.classList.add('current')
149-
})
150-
})
151-
152-
document.body.addEventListener('htmx:responseError', function (event) {
153-
// If you get a 404 error while clicking on a hx-get link, actually open the link
154-
// This is needed because the browser doesn't update the URL when the response is a 404
155-
// In production, cloudfront handles serving the 404 page.
156-
// Locally, the DocumentationWebHost handles it.
157-
// On previews, a generic 404 page is shown.
158-
if (event.detail.xhr.status === 404) {
159-
window.location.assign(event.detail.pathInfo.requestPath)
147+
)
148+
149+
document.body.addEventListener(
150+
'htmx:pushedIntoHistory',
151+
function (event: HtmxEvent) {
152+
const pagesNav = $('#pages-nav')
153+
const currentNavItem = $$('.current', pagesNav)
154+
currentNavItem.forEach((el) => {
155+
el.classList.remove('current')
156+
})
157+
const navItems = $$('a[href="' + event.detail.path + '"]', pagesNav)
158+
navItems.forEach((navItem) => {
159+
navItem.classList.add('current')
160+
})
160161
}
161-
})
162+
)
163+
164+
document.body.addEventListener(
165+
'htmx:responseError',
166+
function (event: HtmxEvent) {
167+
// If you get a 404 error while clicking on a hx-get link, actually open the link
168+
// This is needed because the browser doesn't update the URL when the response is a 404
169+
// In production, cloudfront handles serving the 404 page.
170+
// Locally, the DocumentationWebHost handles it.
171+
// On previews, a generic 404 page is shown.
172+
if (event.detail.xhr.status === 404) {
173+
window.location.assign(event.detail.pathInfo.requestPath)
174+
}
175+
}
176+
)
162177

163178
// We add a query string to the get request to make sure the requested page is up to date
164-
const docsBuilderVersion = $('body').dataset.docsBuilderVersion
165-
document.body.addEventListener('htmx:configRequest', function (event) {
166-
if (event.detail.verb === 'get') {
167-
event.detail.parameters['v'] = docsBuilderVersion
179+
const docsBuilderVersion = $('body')?.dataset.docsBuilderVersion
180+
document.body.addEventListener(
181+
'htmx:configRequest',
182+
function (event: HtmxEvent) {
183+
if (event.detail.verb === 'get' && docsBuilderVersion) {
184+
event.detail.parameters['v'] = docsBuilderVersion
185+
}
168186
}
169-
})
187+
)
170188

171189
// Here we need to strip the v parameter from the URL so
172190
// that the browser doesn't show the v parameter in the address bar
173-
document.body.addEventListener('htmx:beforeHistoryUpdate', function (event) {
174-
const params = new URLSearchParams(
175-
event.detail.history.path.split('?')[1] ?? ''
176-
)
177-
params.delete('v')
178-
const pathWithoutQueryString = event.detail.history.path.split('?')[0]
179-
if (params.size === 0) {
180-
event.detail.history.path = pathWithoutQueryString
181-
} else {
182-
event.detail.history.path =
183-
pathWithoutQueryString + '?' + params.toString()
191+
document.body.addEventListener(
192+
'htmx:beforeHistoryUpdate',
193+
function (event: HtmxEvent) {
194+
const params = new URLSearchParams(
195+
event.detail.history.path.split('?')[1] ?? ''
196+
)
197+
params.delete('v')
198+
const pathWithoutQueryString = event.detail.history.path.split('?')[0]
199+
if (params.size === 0) {
200+
event.detail.history.path = pathWithoutQueryString
201+
} else {
202+
event.detail.history.path =
203+
pathWithoutQueryString + '?' + params.toString()
204+
}
184205
}
185-
})
206+
)

src/Elastic.Documentation.Site/Assets/pages-nav.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
11
import { $, $$ } from 'select-dom'
22

33
function expandAllParents(navItem: HTMLElement) {
4-
let parent = navItem?.closest('li')
4+
let parent: HTMLLIElement | null | undefined = navItem?.closest('li')
55
while (parent) {
66
const input = parent.querySelector('input')
7-
if (input) {
8-
;(input as HTMLInputElement).checked = true
7+
if (input instanceof HTMLInputElement) {
8+
input.checked = true
99
}
1010
parent = parent.parentElement?.closest('li')
1111
}
1212
}
1313

1414
function scrollCurrentNaviItemIntoView(nav: HTMLElement) {
1515
const currentNavItem = $('.current', nav)
16-
expandAllParents(currentNavItem)
16+
17+
if (currentNavItem) {
18+
expandAllParents(currentNavItem)
19+
}
20+
1721
if (currentNavItem && !isElementInViewport(nav, currentNavItem)) {
1822
const navRect = nav.getBoundingClientRect()
1923
const currentNavItemRect = currentNavItem.getBoundingClientRect()
@@ -65,10 +69,13 @@ export function initNav() {
6569
}
6670

6771
const pagesDropdown = $('#pages-dropdown')
72+
if (pagesDropdown) {
73+
setDropdown(pagesDropdown)
74+
}
6875
const pageVersionDropdown = $('#page-version-dropdown')
69-
setDropdown(pagesDropdown)
70-
setDropdown(pageVersionDropdown)
71-
76+
if (pageVersionDropdown) {
77+
setDropdown(pageVersionDropdown)
78+
}
7279
const navItems = $$(
7380
'a[href="' +
7481
window.location.pathname +

src/Elastic.Documentation.Site/Assets/smooth-scroll.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ import { $$ } from 'select-dom'
33
export function initSmoothScroll() {
44
$$('#markdown-content a[href^="#"]').forEach((el) => {
55
el.addEventListener('click', (e) => {
6-
const target = document.getElementById(
7-
el.getAttribute('href').slice(1)
8-
)
6+
// Using ! because href is guaranteed to be present due to the selector
7+
const id = el.getAttribute('href')!.slice(1) // remove the '#' character
8+
const target = document.getElementById(id)
99
if (target) {
1010
e.preventDefault()
1111
target.scrollIntoView({ behavior: 'smooth' })

0 commit comments

Comments
 (0)