Skip to content

Commit 9ab9845

Browse files
committed
refactor: add changes after review
1 parent 25b0fa2 commit 9ab9845

7 files changed

Lines changed: 58 additions & 60 deletions

File tree

.github/workflows/deploy.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,24 @@ jobs:
3030
case "${{ github.ref }}" in
3131
"refs/heads/master")
3232
echo "::set-output name=deploy_dir::./"
33+
echo "::set-output name=public_path::/"
3334
;;
3435
"refs/heads/v8_maintenance")
3536
echo "::set-output name=deploy_dir::v8"
37+
echo "::set-output name=public_path::/v8/"
3638
;;
3739
"refs/heads/v9_maintenance")
3840
echo "::set-output name=deploy_dir::v9"
41+
echo "::set-output name=public_path::/v9/"
3942
;;
4043
"refs/heads/v10_maintenance")
4144
echo "::set-output name=deploy_dir::v10"
45+
echo "::set-output name=public_path::/v10/"
4246
;;
4347
esac
4448
- name: Build docs-app
49+
env:
50+
PUBLIC_PATH: ${{ steps.set-build-dir.outputs.public_path }}
4551
run: pnpm run build:docs
4652
- name: Copy index.html to 404.html for GitHub Pages
4753
run: cp ./packages/__docs__/__build__/index.html ./packages/__docs__/__build__/404.html

.github/workflows/preview.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
runs-on: ubuntu-latest
1515
env:
1616
GITHUB_PULL_REQUEST_PREVIEW: 'true'
17-
PR_NUMBER: ${{ github.event.pull_request.number }}
17+
PUBLIC_PATH: /pr-preview/pr-${{ github.event.pull_request.number }}/
1818
steps:
1919
- uses: actions/checkout@v4
2020
- uses: pnpm/action-setup@v4

packages/__docs__/src/App/index.tsx

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ import {
7070
import {
7171
parseCurrentUrl,
7272
navigateToVersion,
73-
getAssetBasePath,
73+
getDeployBase,
7474
MINOR_VERSION_REGEX
7575
} from '../navigationUtils'
7676

@@ -136,7 +136,7 @@ class App extends Component<AppProps, AppState> {
136136
}
137137

138138
getDocsBasePath = () => {
139-
const base = getAssetBasePath()
139+
const base = getDeployBase()
140140
const { selectedMinorVersion } = this.state
141141
if (selectedMinorVersion) {
142142
return `${base}/docs/${selectedMinorVersion}/`
@@ -212,13 +212,13 @@ class App extends Component<AppProps, AppState> {
212212
navigateToVersion(newVersion)
213213

214214
this.fetchMainDocsData(
215-
`${getAssetBasePath()}/docs/${newVersion}/markdown-and-sources-data.json`,
215+
`${getDeployBase()}/docs/${newVersion}/markdown-and-sources-data.json`,
216216
signal
217217
).catch(errorHandler)
218218

219219
// Icons are not version-specific; only re-fetch if not already loaded
220220
if (!this.state.legacyIconsData) {
221-
fetch(`${getAssetBasePath()}/legacy-icons-data.json`, { signal })
221+
fetch(`${getDeployBase()}/legacy-icons-data.json`, { signal })
222222
.then((response) => response.json())
223223
.then((legacyIconsData) => {
224224
this.setState({ legacyIconsData })
@@ -282,7 +282,7 @@ class App extends Component<AppProps, AppState> {
282282
this.fetchVersionData(signal).catch(errorHandler)
283283
document.addEventListener('keydown', this.handleTabKey)
284284

285-
fetch(`${getAssetBasePath()}/legacy-icons-data.json`, { signal })
285+
fetch(`${getDeployBase()}/legacy-icons-data.json`, { signal })
286286
.then((response) => response.json())
287287
.then((iconsData) => this.setState({ legacyIconsData: iconsData }))
288288
.catch(errorHandler)
@@ -304,13 +304,13 @@ class App extends Component<AppProps, AppState> {
304304
selectedMinorVersion
305305
})
306306
return this.fetchMainDocsData(
307-
`${getAssetBasePath()}/docs/${selectedMinorVersion}/markdown-and-sources-data.json`,
307+
`${getDeployBase()}/docs/${selectedMinorVersion}/markdown-and-sources-data.json`,
308308
signal
309309
)
310310
}
311311
// No minor versions available, fetch from root path
312312
return this.fetchMainDocsData(
313-
`${getAssetBasePath()}/markdown-and-sources-data.json`,
313+
`${getDeployBase()}/markdown-and-sources-data.json`,
314314
signal
315315
)
316316
})
@@ -360,23 +360,21 @@ class App extends Component<AppProps, AppState> {
360360
getPathInfo = () => {
361361
const { hash, pathname } = window.location
362362

363-
const cleanPath = pathname.replace(/^\/+|\/+$/g, '')
364-
const segments = cleanPath.split('/').filter(Boolean)
365-
366-
// Skip PR preview prefix
367-
let idx = 0
363+
// Strip the deploy base (e.g. '/latest', '/pr-preview/pr-123',
364+
// '/<repo>/pr-preview/pr-N') before parsing app segments.
365+
const deployBase = getDeployBase()
366+
let rest = pathname
368367
if (
369-
segments.length >= 2 &&
370-
segments[0] === 'pr-preview' &&
371-
segments[1].startsWith('pr-')
368+
deployBase &&
369+
(rest === deployBase || rest.startsWith(deployBase + '/'))
372370
) {
373-
idx = 2
371+
rest = rest.slice(deployBase.length)
374372
}
375373

376-
// Skip /latest/ prefix
377-
if (idx === 0 && segments[idx] === 'latest') {
378-
idx++
379-
}
374+
const cleanPath = rest.replace(/^\/+|\/+$/g, '')
375+
const segments = cleanPath.split('/').filter(Boolean)
376+
377+
let idx = 0
380378

381379
// Skip minor version prefix (e.g. v11_7)
382380
if (idx < segments.length && MINOR_VERSION_REGEX.test(segments[idx])) {

packages/__docs__/src/index.html

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@
66
deploy base -->
77
<script>
88
;(function () {
9-
var base = '<%= PUBLIC_PATH %>'
10-
var l = window.location
11-
if (l.pathname === base) return
12-
if (l.pathname + '/' === base) return
13-
if (l.pathname.indexOf(base) !== 0) return
14-
var rest = l.pathname.slice(base.length)
15-
l.replace(
16-
base + '?__spa_route=' + encodeURIComponent('/' + rest + l.hash)
9+
const base = '<%= PUBLIC_PATH %>'
10+
const { pathname, search, hash } = window.location
11+
if (pathname === base || pathname + '/' === base) return
12+
if (!pathname.startsWith(base)) return
13+
const rest = pathname.slice(base.length)
14+
window.location.replace(
15+
base +
16+
'?__spa_route=' +
17+
encodeURIComponent('/' + rest + search + hash)
1718
)
1819
})()
1920
</script>

packages/__docs__/src/navigationUtils.ts

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,14 @@ declare const __webpack_public_path__: string
2929
const MINOR_VERSION_REGEX = /^v\d+_\d+$/
3030

3131
type ParsedUrl = {
32-
basePrefix: string
3332
minorVersion: string | null
3433
page: string
3534
sectionId: string | undefined
3635
}
3736

3837
/**
39-
* Returns '' for a root deploy, '/latest' on instructure.design,
40-
* '/pr-preview/pr-<n>' for PR previews. For sub-host deployments it can be
41-
* '/<repo>/pr-preview/pr-<n>'.
38+
* Returns webpack's `output.publicPath` with the trailing slash stripped.
39+
* Always begins with `/`, or is empty for a root deploy.
4240
*/
4341
function getDeployBase(): string {
4442
if (typeof __webpack_public_path__ === 'string' && __webpack_public_path__) {
@@ -52,21 +50,18 @@ function parseCurrentUrl(): ParsedUrl {
5250

5351
const deployBase = getDeployBase()
5452
let rest = pathname
55-
if (deployBase && rest.startsWith(deployBase)) {
53+
if (
54+
deployBase &&
55+
(rest === deployBase || rest.startsWith(deployBase + '/'))
56+
) {
5657
rest = rest.slice(deployBase.length)
5758
}
5859

5960
const cleanPath = rest.replace(/^\/+|\/+$/g, '')
6061
const segments = cleanPath.split('/').filter(Boolean)
6162

62-
let appPrefix = ''
6363
let idx = 0
6464

65-
if (segments[idx] === 'latest') {
66-
appPrefix = '/latest'
67-
idx++
68-
}
69-
7065
// Detect minor version prefix: /v11_7
7166
let minorVersion: string | null = null
7267
if (idx < segments.length && MINOR_VERSION_REGEX.test(segments[idx])) {
@@ -83,7 +78,7 @@ function parseCurrentUrl(): ParsedUrl {
8378
sectionId = decodeURI(hash.replace(/^#+/, ''))
8479
}
8580

86-
return { basePrefix: deployBase + appPrefix, minorVersion, page, sectionId }
81+
return { minorVersion, page, sectionId }
8782
}
8883

8984
type BuildUrlOptions = {
@@ -98,7 +93,7 @@ function buildUrl(targetPage: string, options?: BuildUrlOptions): string {
9893
? options.minorVersion
9994
: parsed.minorVersion
10095

101-
let url = parsed.basePrefix
96+
let url = getDeployBase()
10297

10398
if (minorVersion) {
10499
url += `/${minorVersion}`
@@ -130,20 +125,12 @@ function navigateToVersion(version: string | null): void {
130125
window.dispatchEvent(new PopStateEvent('popstate'))
131126
}
132127

133-
/**
134-
* Returns the base path prefix for fetching static assets.
135-
* On PR previews this is e.g. `/pr-preview/pr-2425`, otherwise empty string.
136-
*/
137-
function getAssetBasePath(): string {
138-
return getDeployBase()
139-
}
140-
141128
export {
142129
parseCurrentUrl,
143130
buildUrl,
144131
navigateTo,
145132
navigateToVersion,
146-
getAssetBasePath,
133+
getDeployBase,
147134
MINOR_VERSION_REGEX
148135
}
149136
export type { ParsedUrl }

packages/__docs__/src/versionData.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const fetchVersionData = async (signal: AbortSignal) => {
5555
}
5656

5757
import type { MinorVersionData } from '../buildScripts/DataTypes.mts'
58-
import { getAssetBasePath } from './navigationUtils'
58+
import { getDeployBase } from './navigationUtils'
5959

6060
/**
6161
* Fetches minor version data from docs-versions.json.
@@ -66,7 +66,9 @@ const fetchMinorVersionData = async (
6666
signal: AbortSignal
6767
): Promise<MinorVersionData | undefined> => {
6868
try {
69-
const result = await fetch(`${getAssetBasePath()}/docs-versions.json`, { signal })
69+
const result = await fetch(`${getDeployBase()}/docs-versions.json`, {
70+
signal
71+
})
7072
if (!result.ok) {
7173
return undefined
7274
}

packages/__docs__/webpack.config.mjs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,19 @@ import webpack from 'webpack'
3131
const ENV = process.env.NODE_ENV || 'production'
3232
const DEBUG = process.env.DEBUG || ENV === 'development'
3333
const GITHUB_PULL_REQUEST_PREVIEW = process.env.GITHUB_PULL_REQUEST_PREVIEW || 'false'
34-
const PR_NUMBER = process.env.PR_NUMBER
35-
// The URL prefix this build is deployed under. Must end with a trailing
34+
// The URL prefix this build is deployed under. Must begin and end with a
3635
// slash. Fed into output.publicPath (which webpack exposes at runtime as
3736
// __webpack_public_path__) and into the HTML template's <base href> and
38-
// 404 SPA-redirect script. Keeping a single source here means a new deploy
39-
// target only needs to set this one env var.
40-
const PUBLIC_PATH =
41-
process.env.PUBLIC_PATH ||
42-
(PR_NUMBER ? `/pr-preview/pr-${PR_NUMBER}/` : '/')
37+
// 404 SPA-redirect script. Every CI workflow sets this explicitly; the
38+
// fallback to '/' only exists for local dev (`pnpm dev`).
39+
const PUBLIC_PATH = process.env.PUBLIC_PATH || '/'
40+
41+
if (!/^\/([^?#]*\/)?$/.test(PUBLIC_PATH)) {
42+
throw new Error(
43+
`PUBLIC_PATH must begin and end with a slash and contain no query or fragment (got: "${PUBLIC_PATH}"). ` +
44+
`Examples: "/", "/latest/", "/pr-preview/pr-123/", "/repo/pr-preview/pr-123/"`
45+
)
46+
}
4347

4448
const outputPath = resolvePath(import.meta.dirname, '__build__')
4549

0 commit comments

Comments
 (0)