@@ -6,6 +6,57 @@ import ReactMarkdown from "react-markdown";
6
6
import entries from "@generated/ecosystem-data/default/entries.json" ;
7
7
import getLogoAsset from "./lib/ecosystem/getLogoAsset.js" ;
8
8
9
+ function humanizeSegment ( segment ) {
10
+ const words = segment . replace ( / - / g, " " ) . split ( " " ) ;
11
+
12
+ // Filter out words with more than 3 digits, this is a heuristic to avoid URL
13
+ // ids and so on.
14
+ const filteredWords = words . filter ( ( word ) => {
15
+ const digitCount = ( word . match ( / \d / g) || [ ] ) . length ;
16
+ return digitCount <= 3 ;
17
+ } ) ;
18
+
19
+ return filteredWords
20
+ . map ( ( word ) => word . charAt ( 0 ) . toUpperCase ( ) + word . slice ( 1 ) )
21
+ . map ( ( word ) => {
22
+ if ( word . toLowerCase ( ) === "opa" ) return "OPA" ;
23
+ return word . charAt ( 0 ) . toUpperCase ( ) + word . slice ( 1 ) ;
24
+ } )
25
+ . join ( " " ) ;
26
+ }
27
+
28
+ function getHumanLabelFromUrl ( url ) {
29
+ try {
30
+ const parsed = new URL ( url ) ;
31
+ const domain = parsed . hostname . replace ( / ^ w w w \. / , "" ) ;
32
+
33
+ const parts = parsed . pathname
34
+ . split ( "/" )
35
+ . filter ( Boolean )
36
+ . map ( humanizeSegment ) ;
37
+
38
+ const label = parts . length > 0 ? parts . join ( " > " ) : domain ;
39
+
40
+ return { domain, label } ;
41
+ } catch ( err ) {
42
+ console . error ( err ) ;
43
+ return { domain : "" , label : url } ;
44
+ }
45
+ }
46
+
47
+ const HumanLink = ( { href } ) => {
48
+ const { domain, label } = getHumanLabelFromUrl ( href ) ;
49
+
50
+ return (
51
+ < >
52
+ < a href = { href } target = "_blank" rel = "noopener noreferrer" >
53
+ { label }
54
+ </ a > { " " }
55
+ ({ domain } )
56
+ </ >
57
+ ) ;
58
+ } ;
59
+
9
60
const EcosystemEntry = ( props ) => {
10
61
const { id } = props . route . customData ;
11
62
const page = entries [ id ] ;
@@ -65,9 +116,7 @@ const EcosystemEntry = (props) => {
65
116
< ul >
66
117
{ blogs . map ( ( url , idx ) => (
67
118
< li key = { `blog-${ idx } ` } >
68
- < a href = { url } target = "_blank" rel = "noopener noreferrer" >
69
- { url }
70
- </ a >
119
+ < HumanLink href = { url } />
71
120
</ li >
72
121
) ) }
73
122
</ ul >
@@ -81,9 +130,7 @@ const EcosystemEntry = (props) => {
81
130
< ul >
82
131
{ code . map ( ( url , idx ) => (
83
132
< li key = { `code-${ idx } ` } >
84
- < a href = { url } target = "_blank" rel = "noopener noreferrer" >
85
- { url }
86
- </ a >
133
+ < HumanLink href = { url } />
87
134
</ li >
88
135
) ) }
89
136
</ ul >
@@ -101,7 +148,7 @@ const EcosystemEntry = (props) => {
101
148
return (
102
149
< li key = { `video-${ idx } ` } >
103
150
< a href = { video } target = "_blank" rel = "noopener noreferrer" >
104
- { video }
151
+ { video . replace ( / h t t p s ? : \/ \/ / , "" ) . replace ( / \/ $ / , "" ) }
105
152
</ a >
106
153
</ li >
107
154
) ;
@@ -143,9 +190,7 @@ const EcosystemEntry = (props) => {
143
190
< ul >
144
191
{ tutorials . map ( ( url , idx ) => (
145
192
< li key = { `tutorial-${ idx } ` } >
146
- < a href = { url } target = "_blank" rel = "noopener noreferrer" >
147
- { url }
148
- </ a >
193
+ < HumanLink href = { url } />
149
194
</ li >
150
195
) ) }
151
196
</ ul >
0 commit comments