Skip to content

Commit

Permalink
fix: 文档内容无标题时的页面滚动报错
Browse files Browse the repository at this point in the history
  • Loading branch information
子奂 committed Aug 12, 2020
1 parent 081d8ae commit a3353a6
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 41 deletions.
43 changes: 19 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,27 @@
![npm](https://img.shields.io/npm/v/markdown-navbar/latest.svg)
![GitHub file size in bytes](https://img.shields.io/github/size/parksben/markdown-navbar/src/index.js)

Best markdown navbar component for React. With this component, you can:
A React component renders an interactive navbar panel of Markdown docs for your blog or website.

- Display article directory for readers
- Click on the anchor point in the directory to jump to the corresponding article content
- Share url with anchor hash value to reader
[![Demo on Netlify](https://screenshots.codesandbox.io/e7e0n.png)](https://csb-e7e0n.netlify.com/)

## 🍭 Demo Online
## Features

Click the thumbnail below to view the demo online:
Implement some regular functions easily by using this component, such as:

<a href="https://csb-e7e0n.netlify.com/" target="_blank" style="display: inline-block; margin-bottom: 32px;">
<img src="https://screenshots.codesandbox.io/e7e0n.png" alt="Demo on Netlify" style="width: 360px; border-radius: 5px; box-shadow: 0 12px 16px 0 rgba(0, 0, 0, 0.32);">
</a>
- Display the structure tree of your article defined by the headings.
- Render anchors that navigate to specific headings in the article.
- Share one URL to readers to navigate to a specific area of the article.

Click the button below to edit & debug it:

<a href="https://codesandbox.io/s/markdown-navbar-demo-online-e7e0n?fontsize=14&hidenavigation=1&theme=dark" target="_blank">
<img src="https://codesandbox.io/static/img/play-codesandbox.svg" alt="Edit markdown-navbar-demo-online">
</a>

## 🍿 Install
## Install

```bash
yarn add markdown-navbar # or `npm i markdown-navbar --save`
```

## 🌭 Quick Start
## Quickstart

[![Edit markdown-navbar-demo-online](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/markdown-navbar-demo-online-e7e0n?fontsize=14&hidenavigation=1&theme=dark)

```jsx
import React from 'react';
Expand Down Expand Up @@ -76,7 +70,13 @@ function App() {
ReactDOM.render(<App />, document.getElementById('root'));
```

## 🍔 Props
## Tips

- The component only parses article headings at level 2 and below. The article title, which is usually used once in an article, will not appear in the navigation bar.
- The component needs to be used in **conjunction** with your article content. When using this component, you must ensure that your article under the same page content.
- Please confirm that every heading of your markdown document is different by each other when the value of property `declarative` is setted as `true`.

## Props

| Property | Data Type | Default Value | Description |
| :--------------: | :-------: | :-------------------------------: | :--------------------------------------------------------------------------------------: |
Expand All @@ -89,11 +89,6 @@ ReactDOM.render(<App />, document.getElementById('root'));
| onNavItemClick | function | (event, element, hashValue) => {} | The event callback function after clicking navbar item |
| onHashChange | function | (newHash, oldHash) => {} | The event callback function before the hash value of browser address changing |

## 🧀 Important Instructions

- This UI component needs to be used in **conjunction** with your article content. When using this component, you must ensure that your article under the same page content.
- Please confirm that every title of your markdown document is different by each other when the property `declarative` is setted as `true`.

## 🍺 License
## License

[MIT license](./LICENSE)
35 changes: 18 additions & 17 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export class MarkdownNavbar extends Component {
currentListNo: '',
});
const headings = document.querySelectorAll('h1, h2, h3, h4, h5, h6');
Array.prototype.slice.apply(headings).forEach(h => (h.dataset.id = ''));
Array.prototype.slice.apply(headings).forEach((h) => (h.dataset.id = ''));

this.scrollEventLockTimer = setTimeout(() => {
this.initHeadingsId();
Expand Down Expand Up @@ -99,7 +99,8 @@ export class MarkdownNavbar extends Component {
text: r.replace(pattOfTitle, '$1'),
}));

const levelCount = level => navData.filter(r => r.level === level).length;
const levelCount = (level) =>
navData.filter((r) => r.level === level).length;
let startLevel = 1;
let startLevelCount = levelCount(startLevel);
while (!startLevelCount) {
Expand All @@ -108,7 +109,7 @@ export class MarkdownNavbar extends Component {
}

let listNo = 1;
navData.forEach(t => {
navData.forEach((t) => {
if (t.level === startLevel) {
t.listNo = listNo.toString();
listNo += 1;
Expand All @@ -130,7 +131,7 @@ export class MarkdownNavbar extends Component {
}
});

const result = navData.map(nav => ({
const result = navData.map((nav) => ({
...nav,
listNo: nav.listNo.indexOf('.') < 0 ? `${nav.listNo}.` : nav.listNo,
text: nav.text,
Expand Down Expand Up @@ -159,12 +160,12 @@ export class MarkdownNavbar extends Component {
: (window.location.hash.match(/heading-\d+/g) || [])[0]
);

this.getNavStructure().forEach(t => {
this.getNavStructure().forEach((t) => {
const headings = document.querySelectorAll(`h${t.level}`);
const curHeading = Array.prototype.slice
.apply(headings)
.find(
h =>
(h) =>
h.innerText.trim() === t.text.trim() &&
(!h.dataset || !h.dataset.id)
);
Expand All @@ -187,14 +188,14 @@ export class MarkdownNavbar extends Component {
getHeadingList() {
const headingList = [];

this.getNavStructure().forEach(t => {
this.getNavStructure().forEach((t) => {
const headings = document.querySelectorAll(`h${t.level}`);
const curHeading = Array.prototype.slice
.apply(headings)
.find(
h =>
(h) =>
h.innerText.trim() === t.text.trim() &&
!headingList.find(x => x.offsetTop === h.offsetTop)
!headingList.find((x) => x.offsetTop === h.offsetTop)
);
if (curHeading) {
headingList.push({
Expand All @@ -220,18 +221,20 @@ export class MarkdownNavbar extends Component {
document.body.scrollTop ||
0;

const newHeadingList = this.getHeadingList().map(h => ({
const newHeadingList = this.getHeadingList().map((h) => ({
...h,
distanceToTop: Math.abs(
scrollTop + this.props.headingTopOffset - h.offsetTop
),
}));
const distanceList = newHeadingList.map(h => h.distanceToTop);
const distanceList = newHeadingList.map((h) => h.distanceToTop);
const minDistance = Math.min(...distanceList);
const curHeading = newHeadingList.find(
h => h.distanceToTop === minDistance
(h) => h.distanceToTop === minDistance
);

if (!curHeading) return;

if (this.props.updateHashAuto) {
// Hash changing callback
if (curHeading.dataId !== this.getCurrentHashValue()) {
Expand Down Expand Up @@ -264,15 +267,15 @@ export class MarkdownNavbar extends Component {
}

render() {
const tBlocks = this.getNavStructure().map(t => {
const tBlocks = this.getNavStructure().map((t) => {
const cls = `title-anchor title-level${t.level} ${
this.state.currentListNo === t.listNo ? 'active' : ''
}`;

return (
<div
className={cls}
onClick={evt => {
onClick={(evt) => {
const currentHash = this.props.declarative
? t.text
: `heading-${t.index}`;
Expand All @@ -292,9 +295,7 @@ export class MarkdownNavbar extends Component {
currentListNo: t.listNo,
});
}}
key={`title_anchor_${Math.random()
.toString(36)
.substring(2)}`}>
key={`title_anchor_${Math.random().toString(36).substring(2)}`}>
{this.props.ordered ? <small>{t.listNo}</small> : null}
{t.text}
</div>
Expand Down

0 comments on commit a3353a6

Please sign in to comment.