Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
50 changes: 30 additions & 20 deletions packages/__docs__/buildScripts/DataTypes.mts
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,15 @@ import type {
SharedTokens
} from '@instructure/ui-themes'

type ProcessedFile =
Documentation &
type ProcessedFile = Documentation &
YamlMetaInfo &
JsDocResult &
PackagePathData &
{ title: string, id:string, componentVersion?: string, componentDirName?: string }
PackagePathData & {
title: string
id: string
componentVersion?: string
componentDirName?: string
}

type PackagePathData = {
extension: string
Expand Down Expand Up @@ -73,10 +76,10 @@ type YamlMetaInfo = {

type JsDocResult = {
// the comment without the comment characters ("/*" etc)
description?: string,
description?: string
// If it's a function it will be the function's name, otherwise
// it's either the string after the '@module' annotation or the variable's name
name?: string,
name?: string
// function params. undefined if the comment is e.g. above imports
params?: {
name: string
Expand All @@ -85,14 +88,14 @@ type JsDocResult = {
optional?: boolean
// the description of the param
description?: string
}[],
}[]
genericParameters?: {
name: string
defaultValue?: string
constraint?: string
}[]
// function return value. undefined if the comment is e.g. above imports
returns?: JSDocFunctionReturns,
returns?: JSDocFunctionReturns
}

type JSDocFunctionReturns = {
Expand Down Expand Up @@ -126,13 +129,16 @@ export type ParsedDoc = {
docs: ParsedDocSummary
}

export type ParsedDocSummary = Record<string,{
title: string
order?: string
category?: string
isWIP?: boolean
tags?: string
}>
export type ParsedDocSummary = Record<
string,
{
title: string
order?: string
category?: string
isWIP?: boolean
tags?: string
}
>

type Glyph = {
bidirectional: boolean
Expand All @@ -153,10 +159,10 @@ type ResolvedColors = {
// canvas / canvas-high-contrast: `key`, `description`) to the new-system
// entries. Not declared per-branch; surfaced as optional on `MainDocsData.themes`.
type ThemeResource =
| (BaseTheme & { resolvedComponents: Record<string, any> }) // legacy-canvas, legacy-canvas-high-contrast
| (NewBaseTheme & { resolvedColors: ResolvedColors }) // canvas, canvas-high-contrast
| (LightTheme & { resolvedColors: ResolvedColors }) // light
| (DarkTheme & { resolvedColors: ResolvedColors }) // dark
| (BaseTheme & { resolvedComponents: Record<string, any> }) // legacy-canvas, legacy-canvas-high-contrast
| (NewBaseTheme & { resolvedColors: ResolvedColors }) // canvas, canvas-high-contrast
| (LightTheme & { resolvedColors: ResolvedColors }) // light
| (DarkTheme & { resolvedColors: ResolvedColors }) // dark
| SharedTokens

type MainDocsData = {
Expand All @@ -167,7 +173,10 @@ type MainDocsData = {
// (BaseTheme & { resolvedComponents }) → has key ✓
// (NewBaseTheme & { resolvedColors }) → gains key? via intersection ✓
// SharedTokens → gains key? via intersection ✓
themes: Record<string, { resource: ThemeResource & { key?: string; description?: string } }>
themes: Record<
string,
{ resource: ThemeResource & { key?: string; description?: string } }
>
library: LibraryOptions
} & ParsedDoc

Expand All @@ -186,6 +195,7 @@ type VersionMap = {
type MinorVersionData = {
libraryVersions: string[]
defaultVersion: string
activeVersions: Record<string, Array<string>>
}

export type {
Expand Down
88 changes: 63 additions & 25 deletions packages/__docs__/buildScripts/build-docs.mts
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ import {
legacyCanvas,
legacyCanvasHighContrast
} from '@instructure/ui-themes'
import type {
MainDocsData,
ProcessedFile,
VersionMap
} from './DataTypes.mjs'
import { buildVersionMap, getPackageShortName, isDocIncludedInVersion } from './utils/buildVersionMap.mjs'
import type { MainDocsData, ProcessedFile, VersionMap } from './DataTypes.mjs'
import {
buildVersionMap,
getPackageShortName,
isDocIncludedInVersion
} from './utils/buildVersionMap.mjs'
import { fileURLToPath, pathToFileURL } from 'url'
import { generateAIAccessibleMarkdowns } from './ai-accessible-documentation/generate-ai-accessible-markdowns.mjs'
import { generateAIAccessibleLlmsFile } from './ai-accessible-documentation/generate-ai-accessible-llms-file.mjs'
Expand Down Expand Up @@ -172,7 +172,9 @@ async function buildDocs() {

const versionDocs = filterDocsForVersion(allDocs, libVersion, versionMap)
// eslint-disable-next-line no-console
console.log(`Generated docs for ${libVersion} (${versionDocs.length} entries)`)
console.log(
`Generated docs for ${libVersion} (${versionDocs.length} entries)`
)

const clientProps = getClientProps(versionDocs)
const mainDocsData: MainDocsData = {
Expand Down Expand Up @@ -208,17 +210,35 @@ async function buildDocs() {

// Write default version's per-doc JSONs to root docs/ as a backward-compatible
// fallback (no version prefix in the path).
const defaultVersionDocs = filterDocsForVersion(allDocs, defaultVersion, versionMap)
const defaultVersionDocs = filterDocsForVersion(
allDocs,
defaultVersion,
versionMap
)
for (const doc of defaultVersionDocs) {
fs.writeFileSync(
buildDir + 'docs/' + doc.id + '.json',
JSON.stringify(doc)
)
}

// builds a map with all the components and collects all the versions a component has in the library. e.g.: the component was introduced only in v11.8 and removed in 11.13, it should not be presented pre 11.8 and post 11.13
const getActiveVersions = () => {
const { libraryVersions, mapping } = versionMap
return libraryVersions.reduce((acc, version) => {
const componentsInThisVersion = Object.keys(mapping[version])
const res: Record<string, Array<string>> = { ...acc }
componentsInThisVersion.forEach((component) => {
res[component] = [...(acc[component] ? acc[component] : []), version]
})
return res
}, {} as Record<string, Array<string>>)
}

// Write version manifest (client only needs versions + default, not the full map)
const docsVersionsManifest = {
libraryVersions: versionMap.libraryVersions,
activeVersions: getActiveVersions(),
defaultVersion
}
fs.writeFileSync(
Expand Down Expand Up @@ -260,12 +280,15 @@ async function buildDocs() {
})

fs.copyFileSync(
projectRoot + '/packages/ui-icons/src/generated/legacy/legacy-icons-data.json',
projectRoot +
'/packages/ui-icons/src/generated/legacy/legacy-icons-data.json',
buildDir + 'legacy-icons-data.json'
)

// eslint-disable-next-line no-console
console.log(`Docs built in ${((Date.now() - startedAt) / 1000).toFixed(1)}s`)
console.log(
`Docs built in ${((Date.now() - startedAt) / 1000).toFixed(1)}s`
)

if (shouldDoTheVersionCopy) {
const versionFilePath = path.resolve(__dirname, '..', 'versions.json')
Expand Down Expand Up @@ -408,7 +431,9 @@ async function parseFilesInParallel(
return slots.filter(Boolean) as ProcessedFile[]
}

function resolveComponents(theme: typeof legacyCanvas | typeof legacyCanvasHighContrast) {
function resolveComponents(
theme: typeof legacyCanvas | typeof legacyCanvasHighContrast
) {
const sem = theme.semantics(theme.primitives)
const resolved: Record<string, any> = {}
for (const [key, fn] of Object.entries(theme.components)) {
Expand All @@ -420,7 +445,9 @@ function resolveComponents(theme: typeof legacyCanvas | typeof legacyCanvasHighC
}

/** Recursively flatten a nested color object, keeping only string values, using the innermost key (e.g. grey.grey10 → grey10) */
function flattenPrimitiveColors(obj: Record<string, any>): Record<string, string> {
function flattenPrimitiveColors(
obj: Record<string, any>
): Record<string, string> {
const result: Record<string, string> = {}
for (const [key, value] of Object.entries(obj)) {
if (typeof value === 'string') {
Expand All @@ -433,7 +460,10 @@ function flattenPrimitiveColors(obj: Record<string, any>): Record<string, string
}

/** Flatten a nested object using camelCase prefix concatenation for the keys */
function flattenSemanticColors(obj: Record<string, any>, prefix = ''): Record<string, string> {
function flattenSemanticColors(
obj: Record<string, any>,
prefix = ''
): Record<string, string> {
const result: Record<string, string> = {}
for (const [key, value] of Object.entries(obj)) {
const fullKey = prefix
Expand Down Expand Up @@ -464,7 +494,10 @@ function parseThemes() {
resource: { ...canvas, resolvedComponents: resolveComponents(legacyCanvas) }
}
parsed['legacy-canvas-high-contrast'] = {
resource: { ...canvasHighContrast, resolvedComponents: resolveComponents(legacyCanvasHighContrast) }
resource: {
...canvasHighContrast,
resolvedComponents: resolveComponents(legacyCanvasHighContrast)
}
}
// `key` is read by Document.tsx's `componentDidUpdate` to detect theme
// changes and refetch the Default Theme Variables. `legacyCanvas` /
Expand Down Expand Up @@ -494,25 +527,30 @@ function parseThemes() {
parsed[light.key] = {
resource: {
...light,
resolvedColors: resolveNewThemeColors(light.newTheme as typeof legacyCanvas),
resolvedComponents: resolveComponents(light.newTheme as typeof legacyCanvas)
resolvedColors: resolveNewThemeColors(
light.newTheme as typeof legacyCanvas
),
resolvedComponents: resolveComponents(
light.newTheme as typeof legacyCanvas
)
}
}
parsed[dark.key] = {
resource: {
...dark,
resolvedColors: resolveNewThemeColors(dark.newTheme as typeof legacyCanvas),
resolvedComponents: resolveComponents(dark.newTheme as typeof legacyCanvas)
resolvedColors: resolveNewThemeColors(
dark.newTheme as typeof legacyCanvas
),
resolvedComponents: resolveComponents(
dark.newTheme as typeof legacyCanvas
)
}
}
const canvasSemantics = legacyCanvas.semantics(legacyCanvas.primitives)
parsed['shared-tokens'] = { resource: legacyCanvas.sharedTokens(canvasSemantics) }
parsed['shared-tokens'] = {
resource: legacyCanvas.sharedTokens(canvasSemantics)
}
return parsed
}

export {
pathsToProcess,
pathsToIgnore,
buildDocs,
filterDocsForVersion
}
export { pathsToProcess, pathsToIgnore, buildDocs, filterDocsForVersion }
28 changes: 22 additions & 6 deletions packages/__docs__/src/App/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -568,10 +568,17 @@ class App extends Component<AppProps, AppState> {
}

renderThemeSelect() {
const currentComponentPackageName =
this.state.currentDocData?.esPath.split('/')[1]

const { minorVersionsData, selectedMinorVersion } = this.state
const allThemeKeys = Object.keys(this.state.docsData!.themes)
const showNewThemes = selectedMinorVersion !== 'v11_6'

const activeComponentVersions = currentComponentPackageName
? minorVersionsData?.activeVersions[currentComponentPackageName]
: []

// The `parsed.themes` map in build-docs.mts contains both:
// - `canvas` / `canvas-high-contrast` → new-system resources (primitives/semantics/sharedTokens/components`)
// - `legacy-canvas` / `legacy-canvas-high-contrast` → legacy wrappers (full theme object)
Expand Down Expand Up @@ -625,8 +632,14 @@ class App extends Component<AppProps, AppState> {
const category = key ? docsData?.docs[key]?.category : undefined
if (!category || !category.startsWith('components')) return null

// Gate on the current component's own versions, not the library's. Packages
// that don't declare `./v11_x` export keys (e.g. ui-motion, ui-position)
// are absent from the version map and so have no `activeVersions` entry —
// hide the select for those rather than rendering it with no options. A
// single applicable version still renders, as a read-out of what the page
// is showing.
const showMinorVersionSelect =
minorVersionsData && minorVersionsData.libraryVersions.length > 1
minorVersionsData && (activeComponentVersions?.length ?? 0) > 0

return themeKeys.length > 1 ? (
<Flex
Expand All @@ -646,11 +659,14 @@ class App extends Component<AppProps, AppState> {
value={selectedMinorVersion ?? this.getLatestMinorVersion()}
width="16.5rem"
>
{[...minorVersionsData!.libraryVersions].reverse().map((ver) => (
<option key={ver} value={ver}>
{formatMinorVersion(ver)}
</option>
))}
{(activeComponentVersions ?? [])
.slice()
.reverse()
.map((ver) => (
<option key={ver} value={ver}>
{formatMinorVersion(ver)}
</option>
))}
</Select>
</Flex.Item>
)}
Expand Down
3 changes: 2 additions & 1 deletion packages/__docs__/src/versionData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ const fetchMinorVersionData = async (
const data = await result.json()
return {
libraryVersions: data.libraryVersions,
defaultVersion: data.defaultVersion
defaultVersion: data.defaultVersion,
activeVersions: data.activeVersions
}
} catch {
return undefined
Expand Down
Loading