To turn a Markdown file into an HTML page, simply place the MD file in the specified directory to display the document content on the page.
The online demo
Obtain the path of the MD file
Get the file name by requiring. Context.
const listFiles=() = >require.context('.. /doc'.true./^\.\/(.+)\.md$/).keys().map(name= >({name:name.replace(/^\.\/(.+)\.md$/.'$1')}));
Copy the code
Use:
const files=listFiles();
Copy the code
The menu
The obtained filename list is used as a menu to redirect the route according to the route query name=filename.
const renderMenu=(menu,inputPath) = >{
return menu.map(item= >{
const {path,name,open,children}=item;
constactive=name===getParams(inputPath).params? .name;if(children? .length){return <li key={path||name} className={open?'open':"'} >
<Link to={{query:{name}}} className={active?'active':"'}preventDefault>
<span>{name}</span>
</Link>
<ul>{renderMenu(children,inputPath)}</ul>
</li>;
}
return <li key={path||name}>
<Link to={{query:{name}}} className={active?'active':"'}stopPropagation>
<span>{name}</span>
</Link>
</li>;
});
};
Copy the code
Turn the md HTML
Load file contents asynchronously from the file name list.
Turn the MD file into HTML by marked, and style the MD file with highlight.js to highlight code blocks.
marked + highlight.js
import marked from 'marked';
import hljs from 'highlight.js';
import 'highlight.js/styles/atom-one-dark.css';
marked.setOptions({
renderer:new marked.Renderer(),
gfm:true.tables:true.breaks:false.pedantic:false.sanitize:false.smartLists:true.smartypants:false.highlight:code= >{
returnhljs.highlightAuto(code).value; }});Copy the code
renderContext
const Index=({name}) = >{
const [context,setContext]=useState(' ');
useEffect(() = >{
const getContext=async() = > {try{
const context=(await import(`.. /.. /doc/${name}.md`))? .default;const newContext=await replacePath(context);
setContext(marked(newContext));
}catch(err){
setContext(err?.message);
}
};
getContext();
},[]);
return <div className="content">{str2React(context)} {! context&&<Spinner global />}
</div>;
};
Copy the code
Route jump and anchor follow
Page routing
const routers=[
{
path:'/'.name:'document'.icon:'HomeOutlined'.component:() = >import('@app/components/renderMd'),}, {path:'/ 404'.name:'404'.component:props= ><span>{props.inputPath} is not found</span>,
hideMenu:true,},];Copy the code
Jump by route query, for example: /doc? Name = filename.
Page rendering
Add a ref to each page to get the offsetTop value of the current page, and scroll the page to the corresponding position when jumping.
const refList=Object.keys(items.current).map(key= >({name:key,offsetTop:items.current[key]? .offsetTop??0}));
Copy the code
The anchor point with
window.addEventListener('scroll',debounce(scrollToAnchor),false);
Copy the code
Listen to scroll (you can add anti-shake function to scroll), scroll to the corresponding document position area, change its routing query value.
const scrollToAnchor=() = >{
if(! isScrolling.current){const offsetTops=sort(Object.keys(items.current).map(key= >({name:key,offsetTop:items.current[key]? .offsetTop??0})),'offsetTop'.true);
const name=offsetTops.find(item= >scrollTop()>=item.offsetTop)? .name;if(currentName.current! ==name){ currentName.current=name; router.push({query:{name}}); }}};Copy the code