@@ -67,6 +67,88 @@ const RawPopup = (() => {
6767 return new TextDecoder ( "utf-8" ) . decode ( bytes ) ;
6868 }
6969
70+ function basename ( path = "" ) {
71+ return path . split ( "/" ) . pop ( ) || path ;
72+ }
73+
74+ function friendlyTitleFromPath ( path = "" ) {
75+ const name = basename ( path ) ;
76+ const knownTitles = {
77+ "LICENSE" : "License" ,
78+ "SECURITY.md" : "Security Policy" ,
79+ "CHANGELOG.md" : "Changelog" ,
80+ "ROADMAP.md" : "Roadmap" ,
81+ "VERSION" : "Version"
82+ } ;
83+
84+ if ( knownTitles [ name ] ) {
85+ return knownTitles [ name ] ;
86+ }
87+
88+ return name
89+ . replace ( / \. [ ^ . ] + $ / , "" )
90+ . replace ( / [ - _ ] + / g, " " )
91+ . replace ( / \b \w / g, ( char ) => char . toUpperCase ( ) ) ;
92+ }
93+
94+ function extractLinkTitle ( link , path ) {
95+ const explicit = ( link . dataset . rawTitle || "" ) . trim ( ) ;
96+ if ( explicit ) {
97+ return explicit ;
98+ }
99+
100+ const labeledChild = link . querySelector ( ".dev-card-title, .ov-name, .install-card-title, .footer-col-title" ) ;
101+ if ( labeledChild && labeledChild . textContent ) {
102+ const label = labeledChild . textContent . trim ( ) ;
103+ if ( label ) {
104+ return label ;
105+ }
106+ }
107+
108+ const aria = ( link . getAttribute ( "aria-label" ) || link . getAttribute ( "title" ) || "" ) . trim ( ) ;
109+ if ( aria ) {
110+ return aria ;
111+ }
112+
113+ return friendlyTitleFromPath ( path ) ;
114+ }
115+
116+ function normalizedHeading ( text = "" ) {
117+ return text
118+ . toLowerCase ( )
119+ . replace ( / [ ` * _ # > - ] + / g, " " )
120+ . replace ( / [ ^ \w \s ] / g, " " )
121+ . replace ( / \s + / g, " " )
122+ . trim ( ) ;
123+ }
124+
125+ function normalizePreviewContent ( content , title , path ) {
126+ let normalized = ( content || "" )
127+ . replace ( / ^ \uFEFF / , "" )
128+ . replace ( / \r \n / g, "\n" ) ;
129+
130+ const lines = normalized . split ( "\n" ) ;
131+ const firstLine = lines [ 0 ] ? lines [ 0 ] . trim ( ) : "" ;
132+ const titleCandidates = [
133+ normalizedHeading ( title ) ,
134+ normalizedHeading ( friendlyTitleFromPath ( path ) ) ,
135+ normalizedHeading ( basename ( path ) )
136+ ] . filter ( Boolean ) ;
137+
138+ if ( firstLine . startsWith ( "#" ) ) {
139+ const heading = normalizedHeading ( firstLine ) ;
140+ if ( titleCandidates . includes ( heading ) ) {
141+ lines . shift ( ) ;
142+ while ( lines [ 0 ] !== undefined && lines [ 0 ] . trim ( ) === "" ) {
143+ lines . shift ( ) ;
144+ }
145+ normalized = lines . join ( "\n" ) ;
146+ }
147+ }
148+
149+ return normalized . trimEnd ( ) ;
150+ }
151+
70152 async function fetchFileContent ( path ) {
71153 const response = await fetch ( DocsHelpers . githubApi ( `/contents/${ path } ?ref=${ DocsData . github . branch } ` ) , {
72154 headers : { Accept : "application/vnd.github+json" }
@@ -103,7 +185,7 @@ const RawPopup = (() => {
103185
104186 viewerTitle . textContent = title || "Repository File" ;
105187 viewerMeta . textContent = `${ path } | inline preview` ;
106- viewerBody . textContent = content ;
188+ viewerBody . textContent = normalizePreviewContent ( content , title , path ) ;
107189 }
108190
109191 function showError ( title , path , message ) {
@@ -124,7 +206,7 @@ const RawPopup = (() => {
124206 return ;
125207 }
126208
127- const title = link . dataset . rawTitle || link . textContent . trim ( ) || path . split ( "/" ) . pop ( ) ;
209+ const title = extractLinkTitle ( link , path ) ;
128210 showLoading ( title , path , href ) ;
129211
130212 try {
0 commit comments