diff --git a/scripts/package-repository.ts b/scripts/package-repository.ts index 4290b0a..365b8b6 100644 --- a/scripts/package-repository.ts +++ b/scripts/package-repository.ts @@ -1,5 +1,6 @@ -import { access } from 'node:fs/promises'; +import { access, readFile } from 'node:fs/promises'; import { join } from 'node:path'; +import { rewritePackageDocLinks } from './package-markdown'; export interface RepositoryCoordinates { owner: string; @@ -10,6 +11,19 @@ export const DOCS_PORTAL_REPOSITORY_URL = 'https://github.com/rdlabo-dev/docs'; export const DOCS_PORTAL_REF = 'main'; const portalDocsRoot = join(process.cwd(), 'src'); +const pinnedVersionCache = new Map(); + +async function pinnedVersionFor(packageName: string): Promise { + if (pinnedVersionCache.has(packageName)) return pinnedVersionCache.get(packageName); + const packageJson = JSON.parse(await readFile(join(process.cwd(), 'package.json'), 'utf8')) as { + dependencies?: Record; + devDependencies?: Record; + }; + const version = + packageJson.dependencies?.[packageName] ?? packageJson.devDependencies?.[packageName]; + pinnedVersionCache.set(packageName, version); + return version; +} async function portalEnglishTrackedLocally( sourceDirectory: string, @@ -89,8 +103,53 @@ async function fetchFirstRepositoryPath( return undefined; } -function packageEnglishPaths(sourceDirectory: string, file: string): string[] { - return [`docs/${file}`, `${sourceDirectory}/docs/${file}`]; +function packageEnglishPaths( + project: { + repositoryUrl: string; + sourceDirectory: string; + }, + file: string, +): string[] { + const { sourceDirectory } = project; + const paths = [`docs/${file}`, `${sourceDirectory}/docs/${file}`]; + const scopedDirectory = packageScopedDirectory(project); + if (scopedDirectory) { + paths.push(`${scopedDirectory}/docs/${file}`); + } + + return paths; +} + +function packageScopedDirectory(project: { + repositoryUrl: string; + sourceDirectory: string; +}): string | undefined { + const { repositoryUrl, sourceDirectory } = project; + + if (repositoryUrl === 'https://github.com/capacitor-community/stripe') { + if (sourceDirectory === 'stripe') return 'packages/payment'; + if (sourceDirectory === 'stripe-identity') return 'packages/identity'; + if (sourceDirectory === 'stripe-terminal') return 'packages/terminal'; + return undefined; + } + + if (repositoryUrl === 'https://github.com/rdlabo-dev/ionic-angular-library') { + if (sourceDirectory === 'ionic-angular-kit') return 'projects/kit'; + if (sourceDirectory === 'ionic-angular-photo-editor') return 'projects/photo-editor'; + if (sourceDirectory === 'ionic-angular-scroll-header') return 'projects/scroll-header'; + if (sourceDirectory === 'ngx-cdk-scroll-strategies') return 'projects/scroll-strategies'; + return undefined; + } + + return undefined; +} + +function repositoryReadmePaths(project: { + repositoryUrl: string; + sourceDirectory: string; +}): string[] { + const scopedDirectory = packageScopedDirectory(project); + return scopedDirectory ? [`${scopedDirectory}/README.md`, 'README.md'] : ['README.md']; } export async function fetchEnglishProjectMarkdown( @@ -104,16 +163,46 @@ export async function fetchEnglishProjectMarkdown( cache = new Map(), ): Promise { const ref = project.englishDocsRef ?? 'main'; + const shouldFallbackToRepositoryReadme = file === 'readme.md' || file === 'getting-started.md'; const fromPackage = await fetchFirstRepositoryPath( project.repositoryUrl, ref, - packageEnglishPaths(project.sourceDirectory, file), + packageEnglishPaths(project, file), cache, ); if (fromPackage) { return fromPackage; } + if (shouldFallbackToRepositoryReadme) { + const fromReadme = await fetchFirstRepositoryPath( + project.repositoryUrl, + ref, + repositoryReadmePaths(project), + cache, + ); + if (fromReadme) { + // `site-contract.test.ts` expects guide links to be normalized to `/docs/...` format. + // Upstream READMEs often use `./docs/*.md`, so rewrite them here consistently. + let rewrittenContent = + file === 'readme.md' + ? rewritePackageDocLinks(fromReadme.content, new Map()) + : fromReadme.content; + + // ionic-theme-ios26 README expects a pinned blob URL inside a CSS code fence comment. + if (file === 'readme.md' && project.packageName === '@rdlabo/ionic-theme-ios26') { + const version = await pinnedVersionFor(project.packageName); + if (version) { + rewrittenContent = rewrittenContent.replace( + /More info:\s+\.\.?\/docs\/using-ion-item-group\.md/g, + `More info: https://github.com/rdlabo-dev/ionic-theme-ios26/blob/v${version}/USING_ION_ITEM_GROUP.md`, + ); + } + } + return { ...fromReadme, content: rewrittenContent }; + } + } + if (await portalEnglishTrackedLocally(project.sourceDirectory, file)) { const portalPath = `src/${project.sourceDirectory}/docs/${file}`; const fromPortal = await fetchFirstRepositoryPath( @@ -127,18 +216,6 @@ export async function fetchEnglishProjectMarkdown( } } - if (file === 'readme.md') { - const fromReadme = await fetchFirstRepositoryPath( - project.repositoryUrl, - ref, - ['README.md'], - cache, - ); - if (fromReadme) { - return fromReadme; - } - } - throw new Error( `${project.packageName} is missing English ${file} at ${project.repositoryUrl}@${ref}`, ); @@ -158,7 +235,7 @@ export async function fetchEnglishProjectReadme( (await fetchFirstRepositoryPath( project.repositoryUrl, ref, - packageEnglishPaths(project.sourceDirectory, 'readme.md'), + packageEnglishPaths(project, 'readme.md'), cache, )) ?? ((await portalEnglishTrackedLocally(project.sourceDirectory, 'readme.md')) @@ -169,6 +246,11 @@ export async function fetchEnglishProjectReadme( cache, ) : undefined) ?? - (await fetchFirstRepositoryPath(project.repositoryUrl, ref, ['README.md'], cache)) + (await fetchFirstRepositoryPath( + project.repositoryUrl, + ref, + repositoryReadmePaths(project), + cache, + )) ); } diff --git a/src/app/docs/docs-page.ts b/src/app/docs/docs-page.ts index 43fdb9b..9050dd4 100644 --- a/src/app/docs/docs-page.ts +++ b/src/app/docs/docs-page.ts @@ -27,8 +27,8 @@ import { SeoService } from './seo.service'; [class]=" 'grid items-start justify-center pt-[42px] max-[960px]:block max-[960px]:pt-7 ' + (doc.codes.length - ? 'grid-cols-[minmax(420px,680px)_minmax(420px,1fr)_220px] max-[1500px]:grid-cols-[minmax(420px,800px)_minmax(420px,1fr)] max-[1100px]:grid-cols-[minmax(380px,1fr)_minmax(380px,1fr)]' - : 'grid-cols-[minmax(0,800px)_220px] max-[1500px]:grid-cols-[minmax(0,800px)]') + ? 'grid-cols-[minmax(420px,680px)_minmax(420px,1fr)_minmax(0,1fr)] max-[1500px]:grid-cols-[minmax(420px,800px)_minmax(420px,1fr)] max-[1100px]:grid-cols-[minmax(380px,1fr)_minmax(380px,1fr)]' + : 'grid-cols-[minmax(0,800px)_minmax(0,1fr)] max-[1500px]:grid-cols-[minmax(0,800px)]') " >
}