diff --git a/public/css/docs/icons/link-icon.svg b/public/css/docs/icons/link-icon.svg new file mode 100644 index 0000000000..abdc8cb884 --- /dev/null +++ b/public/css/docs/icons/link-icon.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/public/css/docs/layout.css b/public/css/docs/layout.css index df018470c0..9270e267be 100644 --- a/public/css/docs/layout.css +++ b/public/css/docs/layout.css @@ -315,6 +315,26 @@ h2 { max-width: 720px; } +.heading-wrapper { + position: relative; +} + +.heading-link { + opacity: 0; + height: 25px; + width: 25px; + background: url(./icons/link-icon.svg); + background-size: 25px 25px; + position: absolute; + left: -30px; + top: 50%; + transform: translateY(-50%); +} + +.heading-wrapper:hover .heading-link { + opacity: 1; +} + .readme > h1, .readme > section h1, .readme > h2, diff --git a/tools/scripts/api-docs/html_fragments.js b/tools/scripts/api-docs/html_fragments.js index 9343f362aa..77604b223b 100644 --- a/tools/scripts/api-docs/html_fragments.js +++ b/tools/scripts/api-docs/html_fragments.js @@ -25,6 +25,9 @@ var join = require( 'path' ).join; var mkdir = require( 'fs' ).mkdirSync; var exists = require( '@stdlib/fs/exists' ).sync; +var readFile = require('@stdlib/fs/read-file').sync; +var readdir = require('@stdlib/fs/read-dir').sync; +var writeFile = require('@stdlib/fs/write-file').sync; var build = require( '@stdlib/_tools/docs/www/readme-fragment-file-tree' ); var stdlibPath = require( './../utils/stdlib_path.js' ); var stdlibVersion = require( './../utils/stdlib_version.js' ); @@ -76,7 +79,57 @@ function main() { throw err; } console.log( 'Finished generating HTML fragments.' ); + processHeadings(dir); } } +/** +* Processes html files to add anchor tag with ids to headings. +* @param {string} baseDir - Api docs directory +*/ + +function processHeadings(baseDir){ + const outputDir = join(baseDir, '@stdlib'); + + function processDir(currentDir){ + const items = readdir(currentDir); + if(items instanceof Error){ + console.error(`Error: ${items.message}`); + return; + } + + items.forEach(item => { + const fullPath = join(currentDir, item) + if(!exists(fullPath)){ + return; + } + + const dirContents = readdir(fullPath); + if(dirContents && !(dirContents instanceof Error)){ + processDir(fullPath); + }else if(item === 'index.html'){ + + let html = readFile(fullPath, 'utf8'); + if(html instanceof Error){ + console.error(`Error: ${html.message}`); + return; + } + + const headingRegex = /<(h[1-6])(.*?)>(.*?)<\/\1>/gi; + html = html.replace(headingRegex, (match, tag, attrs, content) => { + let id = content.toLowerCase().replace(/[^a-z0-9\s]/g, '').trim().replace(/\s+/g, '-').replace(/-+/g, '-'); + return `
<${tag}${attrs}>${content}
`; + }) + + const err = writeFile(fullPath, html); + if(err){ + console.error(`Error: ${err.message}`); + } + } + }); + + } + processDir(outputDir); +} + main();