@@ -32,6 +32,84 @@ export type MarketplacePageData = {
3232 nextPagePath ?: string ;
3333} ;
3434
35+ type MarketplaceMirrorSpec = {
36+ rawUrl : string ;
37+ sourceUrl : string ;
38+ sourceLabel : string ;
39+ ogTitle : string ;
40+ ogDescription : string ;
41+ ogImage : string ;
42+ heroImage : string ;
43+ heroImageAlt : string ;
44+ ciImage : string ;
45+ ciImageAlt : string ;
46+ pitch : string ;
47+ } ;
48+
49+ const marketplaceMirrors : Record <
50+ string ,
51+ Record < string , MarketplaceMirrorSpec >
52+ > = {
53+ "library.inlang.paraglideJs" : {
54+ "/tanstack-router" : {
55+ rawUrl :
56+ "https://raw.githubusercontent.com/TanStack/router/main/examples/react/i18n-paraglide/README.md" ,
57+ sourceUrl :
58+ "https://github.com/TanStack/router/tree/main/examples/react/i18n-paraglide" ,
59+ sourceLabel : "TanStack/router" ,
60+ ogTitle : "The recommended i18n for TanStack Router" ,
61+ ogDescription :
62+ "Type-safe i18n with tiny bundles. Fully integrated with TanStack Router and tested in TanStack's CI/CD pipeline." ,
63+ ogImage : "https://inlang.com/tanstack-router-banner.svg" ,
64+ heroImage : "https://inlang.com/tanstack-router-banner.svg" ,
65+ heroImageAlt : "Paraglide JS for TanStack Router overview" ,
66+ ciImage : "https://inlang.com/images/tanstack-ci-paraglide.svg" ,
67+ ciImageAlt : "Paraglide JS tested in TanStack CI/CD" ,
68+ pitch : [
69+ "- Fully type-safe with IDE autocomplete" ,
70+ "- SEO-friendly localized URLs" ,
71+ "- Works with CSR, SSR, and SSG" ,
72+ "- Tested as part of [TanStack's CI/CD pipeline](https://inlang.com/blog/tanstack-ci)" ,
73+ ] . join ( "\n" ) ,
74+ } ,
75+ "/tanstack-start" : {
76+ rawUrl :
77+ "https://raw.githubusercontent.com/TanStack/router/main/examples/react/start-i18n-paraglide/README.md" ,
78+ sourceUrl :
79+ "https://github.com/TanStack/router/tree/main/examples/react/start-i18n-paraglide" ,
80+ sourceLabel : "TanStack/router" ,
81+ ogTitle : "The recommended i18n for TanStack Start" ,
82+ ogDescription :
83+ "Type-safe i18n with tiny bundles. Fully integrated with TanStack Start and tested in TanStack's CI/CD pipeline." ,
84+ ogImage : "https://inlang.com/tanstack-start-banner.svg" ,
85+ heroImage : "https://inlang.com/tanstack-start-banner.svg" ,
86+ heroImageAlt : "Paraglide JS for TanStack Start overview" ,
87+ ciImage : "https://inlang.com/images/tanstack-ci-paraglide.svg" ,
88+ ciImageAlt : "Paraglide JS tested in TanStack CI/CD" ,
89+ pitch : [
90+ "- Fully type-safe with IDE autocomplete" ,
91+ "- SEO-friendly localized URLs" ,
92+ "- Works with CSR, SSR, and SSG" ,
93+ "- Tested as part of [TanStack's CI/CD pipeline](https://inlang.com/blog/tanstack-ci)" ,
94+ ] . join ( "\n" ) ,
95+ } ,
96+ } ,
97+ } ;
98+
99+ export function getMarketplaceMirrorSpec (
100+ manifestId : string ,
101+ pagePath : string ,
102+ ) : MarketplaceMirrorSpec | undefined {
103+ return marketplaceMirrors [ manifestId ] ?. [ pagePath ] ;
104+ }
105+
106+ export function isMarketplaceMirrorPage (
107+ manifestId : string ,
108+ pagePath : string ,
109+ ) : boolean {
110+ return Boolean ( getMarketplaceMirrorSpec ( manifestId , pagePath ) ) ;
111+ }
112+
35113export async function loadMarketplacePage ( {
36114 uid,
37115 slug,
@@ -99,20 +177,39 @@ export async function loadMarketplacePage({
99177 }
100178
101179 const [ , page ] = pageEntry ;
102- if ( ! page || ! ( await fileExists ( page ) ) ) {
180+ const mirrorSpec = getMarketplaceMirrorSpec ( item . id , pagePath ) ;
181+ if ( ! page || ( ! mirrorSpec && ! ( await fileExists ( page ) ) ) ) {
103182 throw redirect ( { to : itemPath } ) ;
104183 }
105184
106- sourceUrl = page ;
107- const content = await getContentString ( page ) ;
108- rawMarkdownContent = content ;
109- const markdown = await parse ( content ) ;
110- renderedMarkdown = resolveHtmlAssetLinks ( markdown . html , sourceUrl ) ;
111- frontmatter = resolveFrontmatterLinks (
112- markdown . frontmatter as Record < string , { } > | undefined ,
113- sourceUrl ,
114- ) ;
115- imports = frontmatter ?. imports as string [ ] | undefined ;
185+ if ( mirrorSpec ) {
186+ sourceUrl = mirrorSpec . rawUrl ;
187+ const response = await fetch ( mirrorSpec . rawUrl ) ;
188+ if ( ! response . ok ) {
189+ throw redirect ( { to : itemPath } ) ;
190+ }
191+ const exampleContent = await response . text ( ) ;
192+ const mirrorMarkdown = buildMirrorMarkdown ( mirrorSpec , exampleContent ) ;
193+ rawMarkdownContent = mirrorMarkdown ;
194+ const markdown = await parse ( mirrorMarkdown ) ;
195+ renderedMarkdown = resolveHtmlAssetLinks ( markdown . html , sourceUrl ) ;
196+ frontmatter = resolveFrontmatterLinks (
197+ markdown . frontmatter as Record < string , { } > | undefined ,
198+ sourceUrl ,
199+ ) ;
200+ imports = frontmatter ?. imports as string [ ] | undefined ;
201+ } else {
202+ sourceUrl = page ;
203+ const content = await getContentString ( page ) ;
204+ rawMarkdownContent = content ;
205+ const markdown = await parse ( content ) ;
206+ renderedMarkdown = resolveHtmlAssetLinks ( markdown . html , sourceUrl ) ;
207+ frontmatter = resolveFrontmatterLinks (
208+ markdown . frontmatter as Record < string , { } > | undefined ,
209+ sourceUrl ,
210+ ) ;
211+ imports = frontmatter ?. imports as string [ ] | undefined ;
212+ }
116213 } else if ( item . readme ) {
117214 const readme =
118215 typeof item . readme === "object" ? item . readme . en : item . readme ;
@@ -353,15 +450,21 @@ function getMarketplacePageNeighbors(
353450
354451 for ( const [ key , value ] of entries ) {
355452 if ( typeof value === "string" ) {
356- const isExternal = ! value . endsWith ( ".md" ) && ! value . endsWith ( ".html" ) ;
453+ const isExternal =
454+ ! value . endsWith ( ".md" ) &&
455+ ! value . endsWith ( ".html" ) &&
456+ ! isMarketplaceMirrorPage ( manifest . id , key ) ;
357457 if ( ! isExternal ) {
358458 allPages . push ( { route : key , isExternal } ) ;
359459 }
360460 } else {
361461 for ( const [ route , path ] of Object . entries (
362462 value as Record < string , string > ,
363463 ) ) {
364- const isExternal = ! path . endsWith ( ".md" ) && ! path . endsWith ( ".html" ) ;
464+ const isExternal =
465+ ! path . endsWith ( ".md" ) &&
466+ ! path . endsWith ( ".html" ) &&
467+ ! isMarketplaceMirrorPage ( manifest . id , route ) ;
365468 if ( ! isExternal ) {
366469 allPages . push ( { route, isExternal } ) ;
367470 }
@@ -385,3 +488,52 @@ function getMarketplacePageNeighbors(
385488 nextRoute : nextRoute || undefined ,
386489 } ;
387490}
491+
492+ function buildMirrorMarkdown (
493+ spec : MarketplaceMirrorSpec ,
494+ exampleMarkdown : string ,
495+ ) {
496+ const cleaned = stripLeadingMarkdownH1 (
497+ stripFrontmatterBlock ( exampleMarkdown ) ,
498+ ) ;
499+ return [
500+ "---" ,
501+ `og:title: ${ spec . ogTitle } ` ,
502+ `og:description: ${ spec . ogDescription } ` ,
503+ `og:image: ${ spec . ogImage } ` ,
504+ `twitter:image: ${ spec . ogImage } ` ,
505+ `description: ${ spec . ogDescription } ` ,
506+ "---" ,
507+ "" ,
508+ `` ,
509+ "" ,
510+ spec . pitch ,
511+ "" ,
512+ "---" ,
513+ "" ,
514+ "> [!NOTE]" ,
515+ `> This example is mirrored from the official TanStack example in the [${ spec . sourceLabel } ](${ spec . sourceUrl } ) repository.` ,
516+ "" ,
517+ cleaned ,
518+ "" ,
519+ ] . join ( "\n" ) ;
520+ }
521+
522+ function stripFrontmatterBlock ( markdown : string ) {
523+ if ( ! markdown . startsWith ( "---" ) ) return markdown ;
524+ const end = markdown . indexOf ( "\n---" , 3 ) ;
525+ if ( end === - 1 ) return markdown ;
526+ return markdown . slice ( end + 4 ) . trimStart ( ) ;
527+ }
528+
529+ function stripLeadingMarkdownH1 ( markdown : string ) {
530+ const lines = markdown . split ( / \r ? \n / ) ;
531+ let index = 0 ;
532+ while ( index < lines . length && lines [ index ] . trim ( ) === "" ) {
533+ index += 1 ;
534+ }
535+ if ( index < lines . length && lines [ index ] . startsWith ( "# " ) ) {
536+ lines . splice ( index , 1 ) ;
537+ }
538+ return lines . join ( "\n" ) . trimStart ( ) ;
539+ }
0 commit comments