Skip to content

Commit

Permalink
Typescript src/assets (#53110)
Browse files Browse the repository at this point in the history
  • Loading branch information
heiskr authored Nov 14, 2024
1 parent 0a72ea7 commit d35127d
Show file tree
Hide file tree
Showing 10 changed files with 78 additions and 62 deletions.
27 changes: 15 additions & 12 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"delete-orphan-translation-files": "tsx src/workflows/delete-orphan-translation-files.ts",
"deleted-features-pr-comment": "tsx src/data-directory/scripts/deleted-features-pr-comment.ts",
"dev": "cross-env npm start",
"find-orphaned-assets": "node src/assets/scripts/find-orphaned-assets.js",
"find-orphaned-assets": "tsx src/assets/scripts/find-orphaned-assets.ts",
"find-orphaned-features": "tsx src/data-directory/scripts/find-orphaned-features/index.ts",
"find-past-built-pr": "tsx src/workflows/find-past-built-pr.ts",
"find-unused-variables": "tsx src/content-linter/scripts/find-unsed-variables.ts",
Expand Down Expand Up @@ -259,7 +259,7 @@
"express": "4.21.1",
"express-rate-limit": "7.4.0",
"fastest-levenshtein": "1.0.16",
"file-type": "19.4.1",
"file-type": "19.6.0",
"flat": "^6.0.1",
"github-slugger": "^2.0.0",
"glob": "11.0.0",
Expand Down
1 change: 1 addition & 0 deletions src/assets/lib/image-density.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const IMAGE_DENSITY: Record<string, string>
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,19 @@
// [end-readme]

import { program } from 'commander'
import main from './deleted-assets-pr-comment.js'
import main from './deleted-assets-pr-comment'

program
.description('If applicable, print a snippet of Markdown about deleted assets')
.arguments('owner repo base_sha head_sha', 'Simulate what the Actions workflow does')
.arguments('owner repo base_sha head_sha')
.parse(process.argv)

const opts = program.opts()
const args = program.args
type MainArgs = {
owner: string
repo: string
baseSHA: string
headSHA: string
}
const opts = program.opts() as MainArgs

console.log(await main(...args, { ...opts }))
console.log(await main(opts))
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,22 @@ if (!GITHUB_TOKEN) {
// When this file is invoked directly from action as opposed to being imported
if (import.meta.url.endsWith(process.argv[1])) {
const owner = context.repo.owner
const repo = context.payload.repository.name
const baseSHA = context.payload.pull_request.base.sha
const headSHA = context.payload.pull_request.head.sha
const repo = context.payload.repository?.name || ''
const baseSHA = context.payload.pull_request?.base.sha
const headSHA = context.payload.pull_request?.head.sha

const markdown = await main(owner, repo, baseSHA, headSHA)
const markdown = await main({ owner, repo, baseSHA, headSHA })
core.setOutput('markdown', markdown)
}

async function main(owner, repo, baseSHA, headSHA) {
const octokit = github.getOctokit(GITHUB_TOKEN)
type MainArgs = {
owner: string
repo: string
baseSHA: string
headSHA: string
}
async function main({ owner, repo, baseSHA, headSHA }: MainArgs) {
const octokit = github.getOctokit(GITHUB_TOKEN as string)
// get the list of file changes from the PR
const response = await octokit.rest.repos.compareCommitsWithBasehead({
owner,
Expand All @@ -32,6 +38,10 @@ async function main(owner, repo, baseSHA, headSHA) {

const { files } = response.data

if (!files) {
throw new Error('No files found in the PR')
}

const oldFilenames = []
for (const file of files) {
const { filename, status } = file
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const EXCEPTIONS = new Set([
'assets/images/site/apple-touch-icon-76x76.png',
])

function isExceptionPath(imagePath) {
function isExceptionPath(imagePath: string) {
// We also check for .DS_Store because any macOS user that has opened
// a folder with images will have this on disk. It won't get added
// to git anyway thanks to our .DS_Store.
Expand All @@ -53,9 +53,15 @@ program
.option('--exclude-translations', "Don't search in translations/")
.parse(process.argv)

main(program.opts(), program.args)
type MainOptions = {
json: boolean
verbose: boolean
exit: boolean
excludeTranslations: boolean
}
main(program.opts())

async function main(opts) {
async function main(opts: MainOptions) {
const { json, verbose, exit, excludeTranslations } = opts

const walkOptions = {
Expand Down Expand Up @@ -164,7 +170,7 @@ async function main(opts) {
}
}

function getTotalDiskSize(filePaths) {
function getTotalDiskSize(filePaths: Set<string>) {
let sum = 0
for (const filePath of filePaths) {
sum += fs.statSync(filePath).size
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,32 +10,26 @@ import { fileURLToPath } from 'url'
import path from 'path'
import walk from 'walk-sync'
import sharp from 'sharp'
import { chain } from 'lodash-es'
const __dirname = path.dirname(fileURLToPath(import.meta.url))

const imagesPath = path.join(__dirname, '../assets/images')
const imagesExtensions = ['.jpg', '.jpeg', '.png', '.gif']

const files = chain(walk(imagesPath, { directories: false })).filter((relativePath) => {
const files = walk(imagesPath, { directories: false }).filter((relativePath) => {
return imagesExtensions.includes(path.extname(relativePath.toLowerCase()))
})
const infos = await Promise.all(
const images = await Promise.all(
files.map(async (relativePath) => {
const fullPath = path.join(imagesPath, relativePath)
const image = sharp(fullPath)
const { width, height } = await image.metadata()
const size = width * height
const size = (width || 0) * (height || 0)
return { relativePath, width, height, size }
}),
)
const images = files
.map((relativePath, i) => {
return { relativePath, ...infos[i] }
images
.sort((a, b) => b.size - a.size)
.forEach((image) => {
const { relativePath, width, height } = image
console.log(`${width} x ${height} - ${relativePath}`)
})
.orderBy('size', 'desc')
.value()

images.forEach((image) => {
const { relativePath, width, height } = image
console.log(`${width} x ${height} - ${relativePath}`)
})
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import path from 'path'
import { program } from 'commander'
import chalk from 'chalk'
import cheerio from 'cheerio'
// @ts-ignore see https://github.com/sindresorhus/file-type/issues/652
import { fileTypeFromFile } from 'file-type'
import walk from 'walk-sync'
import isSVG from 'is-svg'
Expand All @@ -43,7 +44,7 @@ const EXPECT = {
'.ico': 'image/x-icon',
'.pdf': 'application/pdf',
'.webp': 'image/webp',
}
} as Record<string, string>

const CRITICAL = 'critical'
const WARNING = 'warning'
Expand All @@ -56,7 +57,7 @@ program

main(program.opts())

async function main(opts) {
async function main(opts: { dryRun: boolean; verbose: boolean }) {
let errors = 0

const files = walk(ASSETS_ROOT, { includeBasePath: true, directories: false }).filter(
Expand All @@ -71,7 +72,11 @@ async function main(opts) {
)
},
)
const results = (await Promise.all(files.map(checkFile))).filter(Boolean)
const results = (await Promise.all(files.map(checkFile))).filter(Boolean) as [
level: string,
filePath: string,
error: string,
][]
for (const [level, filePath, error] of results) {
console.log(
level === CRITICAL ? chalk.red(level) : chalk.yellow(level),
Expand All @@ -94,7 +99,7 @@ async function main(opts) {
process.exitCode = errors
}

async function checkFile(filePath) {
async function checkFile(filePath: string) {
const ext = path.extname(filePath)

const { size } = await fs.stat(filePath)
Expand All @@ -113,7 +118,7 @@ async function checkFile(filePath) {
}
try {
checkSVGContent(content)
} catch (error) {
} catch (error: any) {
return [CRITICAL, filePath, error.message]
}
} else if (EXPECT[ext]) {
Expand All @@ -135,15 +140,15 @@ async function checkFile(filePath) {
// All is well. Nothing to complain about.
}

function checkSVGContent(content) {
function checkSVGContent(content: string) {
const $ = cheerio.load(content)
const disallowedTagNames = new Set(['script', 'object', 'iframe', 'embed'])
$('*').each((i, element) => {
const { tagName } = element
const { tagName } = $(element).get(0)
if (disallowedTagNames.has(tagName)) {
throw new Error(`contains a <${tagName}> tag`)
}
for (const key in element.attribs) {
for (const key in $(element).get(0).attribs) {
// Looks for suspicious event handlers on tags.
// For example `<path oNload="alert(1)"" d="M28 0l4.59 4.59-9.76`
// We don't need to do a case-sensitive regex here because cheerio
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { describe, expect, test, vi } from 'vitest'
import { get } from '#src/tests/helpers/e2etest.js'
import { checkCachingHeaders } from '#src/tests/helpers/caching-headers.js'

function getNextStaticAsset(directory) {
function getNextStaticAsset(directory: string) {
const root = path.join('.next', 'static', directory)
const files = fs.readdirSync(root)
if (!files.length) throw new Error(`Can't find any files in ${root}`)
Expand Down
12 changes: 2 additions & 10 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
{
"compilerOptions": {
"target": "ES2022",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
Expand All @@ -30,9 +26,5 @@
"docs-internal-data",
"src/code-scanning/scripts/generate-code-scanning-query-list.ts"
],
"include": [
"*.d.ts",
"**/*.ts",
"**/*.tsx"
]
"include": ["*.d.ts", "**/*.ts", "**/*.tsx"]
}

0 comments on commit d35127d

Please sign in to comment.