Skip to content
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,5 @@ packages/typescriptlang-org/src/lib/documentationNavigation.ts
!**/.vscode/extensions.json

*.tsbuildinfo
# astro
.astro/
4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,7 @@
"sharp": "0.28.1"
},
"patchedDependencies": {
"react-server-dom-webpack@0.0.0-experimental-c8b778b7f-20220825": "patches/react-server-dom-webpack@0.0.0-experimental-c8b778b7f-20220825.patch",
"react-intl@3.12.1": "patches/react-intl@3.12.1.patch",
"gatsby-remark-shiki-twoslash@3.0.38": "patches/gatsby-remark-shiki-twoslash@3.0.38.patch"
"react-intl@3.12.1": "patches/react-intl@3.12.1.patch"
}
},
"jest": {
Expand Down
4 changes: 2 additions & 2 deletions packages/playground-examples/scripts/copyFiles.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@

const copyDir = join(__dirname, "..", "copy");
const jsonDir = join(__dirname, "..", "generated");
const outDir = join(__dirname, "..", "..", "typescriptlang-org", "static", "js", "examples");
const outDir = join(__dirname, "..", "..", "typescriptlang-org", "public", "js", "examples");

if (!existsSync(outDir)) execSync(`mkdir ${outDir}`);
if (!existsSync(outDir)) execSync(`mkdir -p ${outDir}`);

Check warning

Code scanning / CodeQL

Shell command built from environment values Medium

This shell command depends on an uncontrolled
absolute path
.

Copilot Autofix

AI 2 months ago

In general, the fix is to avoid passing dynamically constructed command strings through a shell. Instead, call the underlying program directly and pass any dynamic values (like paths) as separate arguments, or better, use Node’s own filesystem operations when possible.

For this specific case, the best fix without changing observable functionality is to replace the execSync("mkdir -p ...") invocation with code that creates the directory using Node APIs. Since mkdir -p’s behavior is “create this directory and any missing parents, and don’t error if it already exists,” the direct analogue is fs.mkdirSync(outDir, { recursive: true }), or, since fs-extra is already imported as fse, fse.ensureDirSync(outDir). Using fs-extra keeps the code consistent with the rest of the file.

Concretely:

  • In packages/playground-examples/scripts/copyFiles.js, on line 12, replace if (!existsSync(outDir)) execSync(\mkdir -p ${outDir}`);with a call tofse.ensureDirSync(outDir);`.
  • This removes the shell call entirely, so there is no longer any shell command built from environment values.
  • No new imports are needed; fse is already required from fs-extra.

Suggested changeset 1
packages/playground-examples/scripts/copyFiles.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/packages/playground-examples/scripts/copyFiles.js b/packages/playground-examples/scripts/copyFiles.js
--- a/packages/playground-examples/scripts/copyFiles.js
+++ b/packages/playground-examples/scripts/copyFiles.js
@@ -9,7 +9,7 @@
 const jsonDir = join(__dirname, "..", "generated");
 const outDir = join(__dirname, "..", "..", "typescriptlang-org", "public", "js", "examples");
 
-if (!existsSync(outDir)) execSync(`mkdir -p ${outDir}`);
+if (!existsSync(outDir)) fse.ensureDirSync(outDir);
 
 // Move samples
 fse.copySync(copyDir, outDir);
EOF
@@ -9,7 +9,7 @@
const jsonDir = join(__dirname, "..", "generated");
const outDir = join(__dirname, "..", "..", "typescriptlang-org", "public", "js", "examples");

if (!existsSync(outDir)) execSync(`mkdir -p ${outDir}`);
if (!existsSync(outDir)) fse.ensureDirSync(outDir);

// Move samples
fse.copySync(copyDir, outDir);
Copilot is powered by AI and may make mistakes. Always verify output.

// Move samples
fse.copySync(copyDir, outDir);
Expand Down
2 changes: 1 addition & 1 deletion packages/playground-worker/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"license": "MIT",
"private": true,
"scripts": {
"build": "esbuild index.ts --outdir=../typescriptlang-org/static/js/playground-worker --format=esm --target=es2020 --bundle"
"build": "esbuild index.ts --outdir=../typescriptlang-org/public/js/playground-worker --format=esm --target=es2020 --bundle"
},
"dependencies": {
"esbuild": "^0.17.8"
Expand Down
4 changes: 2 additions & 2 deletions packages/playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
"main": "dist/index.js",
"license": "MIT",
"private": true,
"types": "../../typescriptlang-org/static/js/playground/index.d.ts",
"types": "../../typescriptlang-org/public/js/playground/index.d.ts",
"files": [
"dist"
],
"scripts": {
"//bootstrap": "node scripts/getListOfPluginsFromNPM.js",
"build-fast-test": "esbuild src/index.ts --outdir=../typescriptlang-org/static/js/playground/2 --format=esm --target=es2020 --bundle",
"build-fast-test": "esbuild src/index.ts --outdir=../typescriptlang-org/public/js/playground/2 --format=esm --target=es2020 --bundle",
"build": "tsc",
"test": "jest"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/playground/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"include": ["src"],
"compilerOptions": {
"outDir": "../typescriptlang-org/static/js/playground",
"outDir": "../typescriptlang-org/public/js/playground",
"jsx": "react",
"target": "ES2016",
"module": "AMD",
Expand Down
2 changes: 1 addition & 1 deletion packages/sandbox/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"include": ["src", "src/vendor/lzstring.min.js"],

"compilerOptions": {
"outDir": "../typescriptlang-org/static/js/sandbox",
"outDir": "../typescriptlang-org/public/js/sandbox",
"target": "ES2016",
"module": "AMD",
"lib": ["DOM", "esnext"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ languages.forEach((lang) => {
JSON.stringify({ options: optionsSummary })
);

const jsonDir = new URL("../../../typescriptlang-org/static/js/json/", import.meta.url);
const jsonDir = new URL("../../../typescriptlang-org/public/js/json/", import.meta.url);
if (!existsSync(jsonDir)) mkdirSync(jsonDir);

// This is used by the tsconfig popups
Expand Down
3 changes: 2 additions & 1 deletion packages/tsconfig-reference/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"moduleResolution": "node",
"resolveJsonModule": true,
"allowSyntheticDefaultImports": true,
"target": "es2019"
"target": "es2019",
"skipLibCheck": true
}
}
23 changes: 13 additions & 10 deletions packages/typescriptlang-org/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ typings/
.cache/
public

# astro
.astro/

# Mac files
.DS_Store

Expand All @@ -73,23 +76,23 @@ schema.json
apollo.config.js

# Build artifacts
static/js/sandbox/
!static/js/sandbox/.gitkeep
static/js/playground/
!static/js/playground/.gitkeep
static/js/examples/
!static/js/examples/.gitkeep
static/js/json
static/js/playground-worker/
public/js/sandbox/
!public/js/sandbox/.gitkeep
public/js/playground/
!public/js/playground/.gitkeep
public/js/examples/
!public/js/examples/.gitkeep
public/js/json
public/js/playground-worker/

.now

# No autogenerated types
src/__generated__/*
# gatsby-plugin-typegen doesn't create this file when CI=true
!src/__generated__/gatsby-types.ts
static/assets/typescript-handbook.epub
static/assets/typescript-handbook.pdf
public/assets/typescript-handbook.epub
public/assets/typescript-handbook.pdf

/src/lib/release-info.json

Expand Down
55 changes: 55 additions & 0 deletions packages/typescriptlang-org/astro.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { defineConfig } from 'astro/config';
import react from '@astrojs/react';
import sitemap from '@astrojs/sitemap';
import { DOMParser } from 'xmldom';

// Polyfill DOMParser for SSR so react-intl can format rich text messages
// (equivalent to the old gatsby-ssr.js polyfill)
globalThis.DOMParser = DOMParser;

export default defineConfig({
site: 'https://www.typescriptlang.org',
integrations: [
react(),
sitemap({
filter: (page) =>
!page.includes('/glossary') && !page.includes('/vo/'),
}),
],
build: {
format: 'file',
},
trailingSlash: 'ignore',
redirects: {
'/Tutorial': '/docs',
'/Handbook': '/docs',
'/samples': '/docs',
'/docs/home.html': '/docs',
'/playground': '/play/',
'/docs/home': '/docs',
'/docs/handbook/writing-declaration-files': '/docs/handbook/declaration-files/introduction.html',
'/docs/handbook/writing-declaration-files.html': '/docs/handbook/declaration-files/introduction.html',
'/docs/handbook/writing-definition-files': '/docs/handbook/declaration-files/introduction.html',
'/docs/handbook/typings-for-npm-packages': '/docs/handbook/declaration-files/publishing.html',
'/docs/tutorial.html': '/docs/',
'/docs/handbook/release-notes': '/docs/',
'/docs/handbook/release-notes/overview': '/docs/',
'/docs/handbook/release-notes/overview.html': '/docs',
'/docs/handbook/react-&-webpack.html': 'https://webpack.js.org/guides/typescript/',
'/docs/bootstrap': '/docs/',
'/docs/handbook/esm-node': '/docs/handbook/modules/reference.html#node16-node18-node20-nodenext',
'/docs/handbook/esm-node.html': '/docs/handbook/modules/reference.html#node16-node18-node20-nodenext',
'/docs/handbook/modules': '/docs/handbook/modules/introduction.html',
'/docs/handbook/modules.html': '/docs/handbook/modules/introduction.html',
'/docs/handbook/module-resolution': '/docs/handbook/modules/theory.html#module-resolution',
'/docs/handbook/module-resolution.html': '/docs/handbook/modules/theory.html#module-resolution',
},
vite: {
resolve: {
dedupe: ['react', 'react-dom'],
},
ssr: {
noExternal: ['react-intl', 'intl-format-cache', 'intl-messageformat', 'intl-messageformat-parser', '@formatjs/intl-utils'],
},
},
});
2 changes: 1 addition & 1 deletion packages/typescriptlang-org/gatsby-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ module.exports = {
background_color: `white`,
theme_color: `#3178C6`,
display: `standalone`,
icon: `static/icons/ts-logo-512.png`,
icon: `public/icons/ts-logo-512.png`,
},
},

Expand Down
51 changes: 17 additions & 34 deletions packages/typescriptlang-org/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,71 +5,54 @@
"version": "0.0.0",
"license": "MIT",
"scripts": {
"build": "GATSBY_EXPERIMENTAL_PAGE_BUILD_ON_DATA_CHANGES=true gatsby build",
"clean": "gatsby clean",
"build": "astro build",
"clean": "rm -rf dist .astro",
"bootstrap": "pnpm update-versions",
"update-static-assets": "node scripts/downloadSearchAssets.js",
"update-versions": "node scripts/getTypeScriptNPMVersions.js",
"setup-playground-cache-bust": "node scripts/cacheBustPlayground.mjs",
"create-lighthouse-json": "node scripts/createLighthouseJSON.js",
"compile-index-examples": "twoslash --reactAlso src/components/index/twoslash/*.ts src/components/index/twoslash/*.js src/components/index/twoslash/*.tsx src/components/index/twoslash/generated && node scripts/updateIndexTwoslashExamples.js",
"start": "gatsby develop",
"serve": "gatsby serve",
"test": "pnpm tsc && jest"
"start": "astro dev",
"serve": "astro preview",
"test": "jest"
},
"dependencies": {
"@babel/core": "^7.24.5",
"@astrojs/react": "^4.2.0",
"@astrojs/sitemap": "^3.3.0",
"@formatjs/intl-relativetimeformat": "^4.5.15",
"@types/react-helmet": "^5.0.15",
"@typescript/playground": "workspace:*",
"@typescript/sandbox": "workspace:*",
"@typescript/twoslash": "workspace:*",
"@typescript/vfs": "workspace:*",
"gatsby": "^5.13.5",
"gatsby-link": "5.6.0",
"gatsby-plugin-catch-links": "^5.6.0",
"gatsby-plugin-client-side-redirect": "^1.1.0",
"gatsby-plugin-i18n": "^1.0.1",
"gatsby-plugin-manifest": "^5.6.0",
"gatsby-plugin-offline": "^6.6.0",
"gatsby-plugin-react-helmet": "^6.6.0",
"gatsby-plugin-sass": "^6.6.0",
"gatsby-plugin-sharp": "^5.6.0",
"gatsby-plugin-sitemap": "^6.6.0",
"gatsby-react-router-scroll": "6.6.0",
"gatsby-remark-autolink-headers": "^6.6.0",
"gatsby-remark-copy-linked-files": "^6.6.0",
"gatsby-remark-emojis": "^0.4.3",
"gatsby-remark-images": "^7.6.0",
"gatsby-remark-responsive-iframe": "^6.6.0",
"gatsby-remark-shiki-twoslash": "^3.0.36",
"gatsby-remark-smartypants": "^6.6.0",
"gatsby-source-filesystem": "^5.6.0",
"gatsby-transformer-remark": "^6.6.0",
"astro": "^5.3.0",
"github-slugger": "^1.5.0",
"gray-matter": "^4.0.3",
"jsdom": "^16.2.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-helmet": "^6.1.0",
"react-intl": "^3.12.1",
"remark": "^14.0.3",
"remark-html": "^15.0.2",
"sass": "^1.26.10",
"shiki-twoslash": "^3.1.2",
"ts-debounce": "^2.2.0",
"ts-node": "^10.9.1",
"twoslash-cli": "^1.3.22",
"typescript": "*",
"unified": "^10.1.2",
"remark-parse": "^10.0.2",
"remark-rehype": "^10.1.0",
"rehype-stringify": "^9.0.4",
"rehype-autolink-headings": "^6.1.1",
"rehype-slug": "^5.1.0",
"xml-js": "^1.6.11"
},
"devDependencies": {
"@babel/plugin-syntax-optional-chaining": "^7.8.3",
"@types/jest": "^29.5.12",
"@types/react": "^18.3.2",
"@types/react-dom": "^18.3.0",
"gatsby-plugin-typegen": "^3.1.0",
"gatsby-plugin-typescript": "^5.6.0",
"jest": "^29.5.0",
"monaco-editor": "^0.32.1",
"node-polyfill-webpack-plugin": "^3.0.0",
"semver": "^7.6.2",
"ts-jest": "^29.0.5",
"xmldom": "^0.5.0"
Expand Down
8 changes: 4 additions & 4 deletions packages/typescriptlang-org/scripts/cacheBustPlayground.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ function copyFolderSync(from, to) {
// Create a sha copy of the playground and sandbox folders. We want to have
// a copy (and not just move) because folks rely on the un-prefixed URLs.

copyFolderSync("static/js/playground", `static/js/${gitSha}/playground`)
copyFolderSync("static/js/sandbox", `static/js/${gitSha}/sandbox`)
copyFolderSync("public/js/playground", `public/js/${gitSha}/playground`)
copyFolderSync("public/js/sandbox", `public/js/${gitSha}/sandbox`)
copyFolderSync(
"static/js/playground-worker",
`static/js/${gitSha}/playground-worker`
"public/js/playground-worker",
`public/js/${gitSha}/playground-worker`
)
12 changes: 6 additions & 6 deletions packages/typescriptlang-org/scripts/downloadPlaygroundAssets.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,26 @@ const getFileAndStoreLocally = async (url, path) => {
const go = async () => {
await getFileAndStoreLocally(
"https://unpkg.com/monaco-editor@0.19.0/min/vs/loader.js",
"static/js/vs.loader.js"
"public/js/vs.loader.js"
)

const newLoader = readFileSync("static/js/vs.loader.js", "utf8").replace(
const newLoader = readFileSync("public/js/vs.loader.js", "utf8").replace(
"//# sourceMappingURL=../../min-maps/vs/loader.js.map",
"//# sourceMappingURL=vs.loader.js.map"
)
new writeFileSync("static/js/vs.loader.js", newLoader)
new writeFileSync("public/js/vs.loader.js", newLoader)

await getFileAndStoreLocally(
"https://unpkg.com/monaco-editor@0.19.0/min-maps/vs/loader.js.map",
"static/js/vs.loader.js.map"
"public/js/vs.loader.js.map"
)

const newLoaderMap = readFileSync(
"static/js/vs.loader.js.map",
"public/js/vs.loader.js.map",
"utf8"
).replace('"sources":["vs/vs/loader.js"]', '"sources":["vs.loader.js"]')

new writeFileSync("static/js/vs.loader.js.map", newLoaderMap)
new writeFileSync("public/js/vs.loader.js.map", newLoaderMap)
}

go()
4 changes: 2 additions & 2 deletions packages/typescriptlang-org/scripts/downloadSearchAssets.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const getFileAndStoreLocally = async (url, path, editFunc) => {
const go = async () => {
await getFileAndStoreLocally(
"https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.js",
"static/js/docsearch.js",
"public/js/docsearch.js",
js => {
const fixAriaByDroppingCustomText = js.replace(
'aria-label="Link to the result"',
Expand All @@ -37,7 +37,7 @@ const go = async () => {
// Remove the mapping reference
await getFileAndStoreLocally(
"https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.css",
"static/css/docsearch.css",
"public/css/docsearch.css",
css => {
return css.replace("/*# sourceMappingURL=docsearch.min.css.map */", "")
}
Expand Down
38 changes: 4 additions & 34 deletions packages/typescriptlang-org/src/components/HeadSEO.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,10 @@
import * as React from "react"
import { Helmet } from "react-helmet";
/**
* Legacy Gatsby component — replaced by BaseLayout.astro for <head> management.
* Only the SeoProps type is still used.
*/

export type SeoProps = {
title: string
description: string
ogTags?: { [key: string]: string }
}

export const HeadSEO = (props: SeoProps) => {

const ogTags = {
...props.ogTags,
"og:title": props.title,
"og:description": props.description,
"twitter:site": "typescriptlang",
}



// do we want localized pages to be the english version?
//{seo.url && <meta property="og:url" content={seo.url} />}

// TODO: a lot of pages should have this
// <meta property="og:type" content="article" />

// TODO: Maybe on prod we can generate an image for each file
// <meta name="image" content={seo.image} />

return (
<>
<Helmet title={props.title} titleTemplate={"TypeScript: %s"}>
<meta name="description" key="description" content={props.description} />
{
Object.keys(ogTags).map(k => <meta key={k} property={k} content={ogTags[k]} />)
}
</Helmet>
</>
)
}
Loading
Loading