@@ -12,6 +12,8 @@ import path from "node:path";
1212import { toHtml } from "hast-util-to-html" ;
1313import { JSDOM } from "jsdom" ;
1414
15+ const aElementRegex = / < a .* ?h r e f = " ( .* ?) " .* ?> ( [ ^ < ] * ) < \/ a > / ;
16+
1517function escapeMarkdown ( input ) {
1618 const map = {
1719 "|" : "|"
@@ -66,13 +68,19 @@ async function htmlToMarkdown(options = {}) {
6668 } ,
6769 a ( state , node ) {
6870 // This fixes internal linking e.g. from #~myawesomemethod to #myawesomemethod
69- const regex = / < a .* ?h r e f = " ( .* ?) " .* ?> ( [ ^ < ] * ) < \/ a > / ;
7071 const result = { type : "html" , value : toHtml ( node ) . replaceAll ( "~" , "" ) } ;
71- let href = result . value . match ( regex ) ;
72- if ( href !== null && href [ 1 ] . split ( "#" ) [ 1 ] != null ) {
73- let text = href [ 2 ] ;
72+ let href = result . value . match ( aElementRegex ) ;
73+ // Filters for a tags that need fixing
74+ // href !== null - Checks if href is null (A element has no href)
75+ // href[1].split("#")[1] != null - Checks if the a element is an internal link
76+ // !href[2].includes("line") - Checks for links to GitHub source code
77+ if ( href !== null && href [ 1 ] . split ( "#" ) [ 1 ] != null && ! href [ 2 ] . includes ( "line" ) ) {
78+ const text = href [ 2 ] ;
7479 href = href [ 1 ] ;
75- result . value = result . value . replace ( href , "#" + href . split ( "#" ) [ 1 ] . toLowerCase ( ) ) . replace ( text , text . replace ( href . split ( "#" ) [ 1 ] , "" ) + "#" + href . split ( "#" ) [ 1 ] ) ;
80+ result . value =
81+ result . value . replace ( href , href . split ( "#" ) [ 0 ] + "#" + href . split ( "#" ) [ 1 ] . toLowerCase ( ) )
82+ . replace ( text , text . replace ( href . split ( "#" ) [ 1 ] , "" ) + "#" + href . split ( "#" ) [ 1 ] )
83+ . replace ( "##" , "#" ) ;
7684 }
7785 state . patch ( node , result ) ;
7886 return result ;
@@ -87,6 +95,8 @@ async function htmlToMarkdown(options = {}) {
8795 return String ( file ) ;
8896}
8997
98+ const deadLinks = [ ] ;
99+ const deadLinksCheckPromises = [ ] ;
90100const excludedFiles = { "index.html" : "" , "global.html" : "" , "custom.css" : "" } ;
91101const inputDirectory = path . join ( "dist" , "api" ) ;
92102const outputDirectory = path . join ( "docs" , "api" ) ;
@@ -117,11 +127,11 @@ for (const file of fs.readdirSync(path.join("dist", "api"))) {
117127 if ( file . endsWith ( ".js.html" ) ) continue ;
118128
119129 const filePath = path . join ( inputDirectory , file ) ;
120- const mardownPath = path . join ( outputDirectory , file . replace ( ".html" , ".md" ) ) ;
121130 // Skip directories
122131 if ( fs . statSync ( filePath ) . isDirectory ( ) ) continue ;
123132
124- //console.log("HTML -> Markdown", "|", filePath, "->", mardownPath);
133+ const mardownPath = path . join ( outputDirectory , file . replace ( ".html" , ".md" ) ) ;
134+ console . log ( "HTML -> Markdown" , "|" , filePath , "->" , mardownPath ) ;
125135
126136 // Read the html file
127137 const htmlString = fs . readFileSync ( filePath ) ;
@@ -138,17 +148,43 @@ for (const file of fs.readdirSync(path.join("dist", "api"))) {
138148 markdown = fixMarkdown ( markdown ) ;
139149
140150 // Point all js links to GitHub
141- const linkMatches = markdown . matchAll ( / \( ( . * ? ) \. j s . h t m l \) / g) ;
151+ const linkMatches = markdown . matchAll ( / " [ ^ " ] * \. [ A - Z a - z 0 - 9 ] + \. [ A - Z a - z 0 - 9 ] + [ ^ " ] * " / g) ;
142152 for ( const linkMatch of linkMatches ) {
143- const githubUrl = packageTagName + linkMatch [ 1 ] . replace ( ".js.html" , "" ) . replaceAll ( "_" , "/" ) . replace ( "project" , "" ) + ".js" ;
144- markdown = markdown . replaceAll ( linkMatch [ 1 ] + ".js.html#line" , githubUrl + "#L" ) . replaceAll ( linkMatch [ 1 ] + ".js.html" , githubUrl ) ;
153+ const githubUrl = packageTagName +
154+ linkMatch [ 0 ] . replaceAll ( "\"" , "" ) . replace ( ".js.html" , "" ) . replaceAll ( "_" , "/" ) . replace ( "project" , "" ) +
155+ ".js" ;
156+ markdown = markdown
157+ . replaceAll ( linkMatch [ 0 ] . replaceAll ( "\"" , "" ) + "#line" , githubUrl + "#L" )
158+ . replaceAll ( linkMatch [ 0 ] . replaceAll ( "\"" , "" ) , githubUrl ) ;
159+ }
160+
161+ // Add target="_blank" to the a element (Must link to external site) for a better user experience
162+ markdown = markdown . replaceAll ( "<a href=\"http" , "<a target=\"_blank\" href=\"http" ) ;
163+
164+ for ( const aElement of markdown . matchAll ( aElementRegex + "g" ) ) {
165+ deadLinksCheckPromises . push ( checkDeadlinks ( aElement [ 1 ] , filePath ) ) ;
145166 }
146-
167+
147168 // Save markdown file
148169 fs . writeFileSync (
149170 mardownPath ,
150171 markdown
151172 ) ;
173+
174+ Promise . all ( deadLinksCheckPromises ) ;
175+ }
176+
177+ async function checkDeadlinks ( link , sourcePath ) {
178+ if ( ( await fetch ( link ) ) . status != 200 ) {
179+ deadLinks . push ( {
180+ link : link ,
181+ sourcePath : sourcePath
182+ } ) ;
183+ }
152184}
153185
154- console . log ( "Conversion done" ) ;
186+ console . log ( "Conversion done" ) ;
187+ console . log ( "Found" , deadLinks . length , "dead links" ) ;
188+ if ( deadLinks . length != 0 ) {
189+ console . log ( deadLinks ) ;
190+ }
0 commit comments