@@ -6,6 +6,7 @@ import { DataSource, EntityManager } from 'typeorm';
66import { MentionedUser } from '../schema/comments' ;
77import { EntityTarget } from 'typeorm/common/EntityTarget' ;
88import { ghostUser } from './utils' ;
9+ import { isValidHttpUrl } from './links' ;
910
1011export const markdown : MarkdownIt = MarkdownIt ( {
1112 html : false ,
@@ -126,7 +127,61 @@ markdown.renderer.rules.text = function (tokens, idx, options, env, self) {
126127 return renderMentions ( content , mentions ) ;
127128} ;
128129
130+ /**
131+ * Extracts the text content from a link by looking at tokens following link_open.
132+ * The link text appears in 'text' tokens between link_open and link_close.
133+ */
134+ const getLinkText = ( tokens : Token [ ] , linkOpenIdx : number ) : string => {
135+ let text = '' ;
136+ for ( let i = linkOpenIdx + 1 ; i < tokens . length ; i ++ ) {
137+ if ( tokens [ i ] . type === 'link_close' ) {
138+ break ;
139+ }
140+ if ( tokens [ i ] . type === 'text' ) {
141+ text += tokens [ i ] . content ;
142+ }
143+ }
144+ return text . trim ( ) ;
145+ } ;
146+
147+ /**
148+ * Attempts to convert text to a valid HTTP URL.
149+ * Handles cases like "www.example.com" by prepending "https://".
150+ */
151+ const toValidHttpUrl = ( text : string ) : string | null => {
152+ if ( ! text ) return null ;
153+
154+ // Already a valid HTTP URL
155+ if ( isValidHttpUrl ( text ) ) {
156+ return text ;
157+ }
158+
159+ // Try adding https:// prefix for URLs like www.example.com or example.com
160+ const withProtocol = `https://${ text } ` ;
161+ if ( isValidHttpUrl ( withProtocol ) ) {
162+ return withProtocol ;
163+ }
164+
165+ return null ;
166+ } ;
167+
129168markdown . renderer . rules . link_open = function ( tokens , idx , options , env , self ) {
169+ const token = tokens [ idx ] ;
170+ const hrefIndex = token . attrIndex ( 'href' ) ;
171+
172+ if ( hrefIndex >= 0 && token . attrs ) {
173+ const href = token . attrs [ hrefIndex ] [ 1 ] ;
174+
175+ // If the href is not a valid HTTP URL, try using the link text as the URL
176+ if ( ! isValidHttpUrl ( href ) ) {
177+ const linkText = getLinkText ( tokens , idx ) ;
178+ const validUrl = toValidHttpUrl ( linkText ) ;
179+ if ( validUrl ) {
180+ token . attrs [ hrefIndex ] [ 1 ] = validUrl ;
181+ }
182+ }
183+ }
184+
130185 tokens [ idx ] = setTokenAttribute ( tokens [ idx ] , 'target' , '_blank' ) ;
131186 tokens [ idx ] = setTokenAttribute ( tokens [ idx ] , 'rel' , 'noopener nofollow' ) ;
132187 return defaultRender ( tokens , idx , options , env , self ) ;
0 commit comments