Skip to content

Commit 75f90c9

Browse files
authored
Update current JavaScripts to use Typescript (github#19824)
* Update index to make it clear what has hasn't updated to Next/React yet * Typescriptify events and experiments * Typescript the old JS for easier integration * Update release-notes.ts * Lint * Run npm i * Fix a few lint issues * Update airgap-links.ts * Update airgap-links.ts * Update set-next-env to ts * Update airgap-links.ts * Update package-lock.json * Update set-next-env.ts * Update package-lock.json * Revert "Update package-lock.json" This reverts commit b45e8250beeb700719d3b44e1092b0bbd093baba. * readd fsevents * Revert "readd fsevents" This reverts commit 419f3c35080ac4a9072f0b4e8e291e1712ce3639. * Update openapi-schema-check.yml * Revert "Update openapi-schema-check.yml" This reverts commit 5e9f4a29ea11ee343ca17291a40a751920c5b923. * Update package-lock.json * Update package-lock.json
1 parent 69062b2 commit 75f90c9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+982
-808
lines changed

components/Search.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { useState, useEffect, useRef, ReactNode } from 'react'
22
import { useRouter } from 'next/router'
33
import debounce from 'lodash/debounce'
44
import { useTranslation } from 'components/hooks/useTranslation'
5-
import { sendEvent } from '../javascripts/events'
5+
import { sendEvent, EventType } from '../javascripts/events'
66
import { useMainContext } from './context/MainContext'
77
import { useVersion } from 'components/hooks/useVersion'
88

@@ -126,7 +126,7 @@ export function Search({ isStandalone = false, updateSearchParams = true, childr
126126
// Analytics tracking
127127
if (xquery) {
128128
sendEvent({
129-
type: 'search',
129+
type: EventType.search,
130130
search_query: xquery,
131131
// search_context
132132
})

components/Survey.tsx

+5-5
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { useState, useRef } from 'react'
22
import { ThumbsdownIcon, ThumbsupIcon } from '@primer/octicons-react'
33
import { useTranslation } from 'components/hooks/useTranslation'
44
import { Link } from 'components/Link'
5-
import { sendEvent } from '../javascripts/events'
5+
import { sendEvent, EventType } from '../javascripts/events'
66

77
enum ViewState {
88
START = 'START',
@@ -137,10 +137,10 @@ function trackEvent(formData: FormData | undefined) {
137137
if (!formData) return
138138
// Nota bene: convert empty strings to undefined
139139
return sendEvent({
140-
type: 'survey',
141-
survey_token: formData.get('survey-token') || undefined, // Honeypot
140+
type: EventType.survey,
141+
survey_token: (formData.get('survey-token') as string) || undefined, // Honeypot
142142
survey_vote: formData.get('survey-vote') === 'Y',
143-
survey_comment: formData.get('survey-comment') || undefined,
144-
survey_email: formData.get('survey-email') || undefined,
143+
survey_comment: (formData.get('survey-comment') as string) || undefined,
144+
survey_email: (formData.get('survey-email') as string) || undefined,
145145
})
146146
}

javascripts/airgap-links.js

-17
This file was deleted.

javascripts/airgap-links.ts

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
export default function airgapLinks() {
2+
// @ts-ignore
3+
if (window.IS_NEXTJS_PAGE) return
4+
5+
// When in an airgapped environment,
6+
// show a tooltip on external links
7+
const exposeEl = document?.getElementById('expose') as HTMLScriptElement
8+
const { airgap } = JSON.parse(exposeEl.text)
9+
if (!airgap) return
10+
11+
const externaLinks = Array.from(document.querySelectorAll('a[href^="http"], a[href^="//"]'))
12+
externaLinks.forEach((link) => {
13+
link.classList.add('tooltipped')
14+
link.setAttribute('aria-label', 'This link may not work in this environment.')
15+
link.setAttribute('rel', 'noopener')
16+
})
17+
}

javascripts/all-articles.js

-18
This file was deleted.

javascripts/all-articles.ts

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/**
2+
* Handles the client-side events for `includes/all-articles.html`.
3+
*/
4+
export default function allArticles() {
5+
const buttons = document.querySelectorAll('button.js-all-articles-show-more')
6+
7+
buttons.forEach((btn) =>
8+
btn.addEventListener('click', (evt) => {
9+
const target = evt.currentTarget as HTMLButtonElement
10+
// Show all hidden links
11+
const hiddenLinks = target?.parentElement?.querySelectorAll('li.d-none')
12+
hiddenLinks?.forEach((link) => link.classList.remove('d-none'))
13+
// Remove the button, since we don't need it anymore
14+
target?.parentElement?.removeChild(target)
15+
})
16+
)
17+
}
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
declare module 'browser-date-formatter' {
2+
export default function browserDateFormatter(): void
3+
}

javascripts/copy-code.js javascripts/copy-code.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ export default () => {
33

44
if (!buttons) return
55

6-
buttons.forEach(button =>
7-
button.addEventListener('click', async evt => {
8-
const text = button.dataset.clipboardText
6+
buttons.forEach((button) =>
7+
button.addEventListener('click', async () => {
8+
const text = (button as HTMLElement).dataset.clipboardText
9+
if (!text) return
910
await navigator.clipboard.writeText(text)
1011

11-
const beforeTooltip = button.getAttribute('aria-label')
12+
const beforeTooltip = button.getAttribute('aria-label') || ''
1213
button.setAttribute('aria-label', 'Copied!')
1314

1415
setTimeout(() => {
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,37 @@
11
const expandText = 'Expand All'
22
const closeText = 'Close All'
33

4-
export default function devToc () {
4+
export default function devToc() {
55
const expandButton = document.querySelector('.js-expand')
66
if (!expandButton) return
77

88
const detailsElements = document.querySelectorAll('details')
99

1010
expandButton.addEventListener('click', () => {
1111
// on click, toggle all the details elements open or closed
12-
const anyDetailsOpen = Array.from(detailsElements).find(details => details.open)
12+
const anyDetailsOpen = Array.from(detailsElements).find((details) => details.open)
1313

14-
for (const detailsElement of detailsElements) {
15-
anyDetailsOpen
16-
? detailsElement.removeAttribute('open')
17-
: detailsElement.open = true
18-
}
14+
detailsElements.forEach((detailsElement) => {
15+
anyDetailsOpen ? detailsElement.removeAttribute('open') : (detailsElement.open = true)
16+
})
1917

2018
// toggle the button text on click
2119
anyDetailsOpen
22-
? expandButton.textContent = expandText
23-
: expandButton.textContent = closeText
20+
? (expandButton.textContent = expandText)
21+
: (expandButton.textContent = closeText)
2422
})
2523

2624
// also toggle the button text on clicking any of the details elements
27-
for (const detailsElement of detailsElements) {
25+
detailsElements.forEach((detailsElement) => {
2826
detailsElement.addEventListener('click', () => {
2927
expandButton.textContent = closeText
3028

3129
// we can only get an accurate count of the open details elements if we wait a fraction after click
3230
setTimeout(() => {
33-
if (!Array.from(detailsElements).find(details => details.open)) {
31+
if (!Array.from(detailsElements).find((details) => details.open)) {
3432
expandButton.textContent = expandText
3533
}
3634
}, 50)
3735
})
38-
}
36+
})
3937
}

javascripts/display-platform-specific-content.js

-87
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import parseUserAgent from './user-agent'
2+
const supportedPlatforms = ['mac', 'windows', 'linux']
3+
const detectedPlatforms = new Set()
4+
5+
// Emphasize content for the visitor's OS (inferred from user agent string)
6+
7+
export default function displayPlatformSpecificContent() {
8+
let platform = getDefaultPlatform() || parseUserAgent().os
9+
10+
// adjust platform names to fit existing mac/windows/linux scheme
11+
if (!platform) platform = 'linux'
12+
if (platform === 'ios') platform = 'mac'
13+
14+
const platformsInContent = findPlatformSpecificContent(platform)
15+
16+
hideSwitcherLinks(platformsInContent)
17+
18+
showContentForPlatform(platform)
19+
20+
// configure links for switching platform content
21+
switcherLinks().forEach((link) => {
22+
link.addEventListener('click', (event) => {
23+
event.preventDefault()
24+
const target = event.target as HTMLElement
25+
showContentForPlatform(target.dataset.platform || '')
26+
findPlatformSpecificContent(target.dataset.platform || '')
27+
})
28+
})
29+
}
30+
31+
function showContentForPlatform(platform: string) {
32+
// (de)activate switcher link appearances
33+
switcherLinks().forEach((link) => {
34+
link.dataset.platform === platform
35+
? link.classList.add('selected')
36+
: link.classList.remove('selected')
37+
})
38+
}
39+
40+
function findPlatformSpecificContent(platform: string) {
41+
// find all platform-specific *block* elements and hide or show as appropriate
42+
// example: {{ #mac }} block content {{/mac}}
43+
const markdowns = Array.from(
44+
document.querySelectorAll('.extended-markdown')
45+
) as Array<HTMLElement>
46+
markdowns
47+
.filter((el) => supportedPlatforms.some((platform) => el.classList.contains(platform)))
48+
.forEach((el) => {
49+
detectPlatforms(el)
50+
el.style.display = el.classList.contains(platform) ? '' : 'none'
51+
})
52+
53+
// find all platform-specific *inline* elements and hide or show as appropriate
54+
// example: <span class="platform-mac">inline content</span>
55+
const platforms = Array.from(
56+
document.querySelectorAll('.platform-mac, .platform-windows, .platform-linux')
57+
) as Array<HTMLElement>
58+
platforms.forEach((el) => {
59+
detectPlatforms(el)
60+
el.style.display = el.classList.contains('platform-' + platform) ? '' : 'none'
61+
})
62+
63+
return Array.from(detectedPlatforms) as Array<string>
64+
}
65+
66+
// hide links for any platform-specific sections that are not present
67+
function hideSwitcherLinks(platformsInContent: Array<string>) {
68+
const links = Array.from(
69+
document.querySelectorAll('a.platform-switcher')
70+
) as Array<HTMLAnchorElement>
71+
links.forEach((link) => {
72+
if (platformsInContent.includes(link.dataset.platform || '')) return
73+
link.style.display = 'none'
74+
})
75+
}
76+
77+
function detectPlatforms(el: HTMLElement) {
78+
el.classList.forEach((elClass) => {
79+
const value = elClass.replace(/platform-/, '')
80+
if (supportedPlatforms.includes(value)) detectedPlatforms.add(value)
81+
})
82+
}
83+
84+
function getDefaultPlatform() {
85+
const el = document.querySelector('[data-default-platform]') as HTMLElement
86+
if (el) return el.dataset.defaultPlatform
87+
}
88+
89+
function switcherLinks(): Array<HTMLAnchorElement> {
90+
return Array.from(document.querySelectorAll('a.platform-switcher'))
91+
}

0 commit comments

Comments
 (0)