mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-09 15:05:44 +01:00
fix timing problem with anchor links on markdown view
This commit is contained in:
@@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
### Fixed
|
### Fixed
|
||||||
- Repository names may not end with ".git" ([#1277](https://github.com/scm-manager/scm-manager/pull/1277))
|
- Repository names may not end with ".git" ([#1277](https://github.com/scm-manager/scm-manager/pull/1277))
|
||||||
- Add preselected value to options in dropdown component if missing ([#1287](https://github.com/scm-manager/scm-manager/pull/1287))
|
- Add preselected value to options in dropdown component if missing ([#1287](https://github.com/scm-manager/scm-manager/pull/1287))
|
||||||
|
- Fix timing problem with anchor links for markdown view ([#1290](https://github.com/scm-manager/scm-manager/pull/1290))
|
||||||
|
|
||||||
## [2.3.1] - 2020-08-04
|
## [2.3.1] - 2020-08-04
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -30,18 +30,23 @@ import ErrorBoundary from "./ErrorBoundary";
|
|||||||
import SyntaxHighlighter from "./SyntaxHighlighter";
|
import SyntaxHighlighter from "./SyntaxHighlighter";
|
||||||
import MarkdownHeadingRenderer from "./MarkdownHeadingRenderer";
|
import MarkdownHeadingRenderer from "./MarkdownHeadingRenderer";
|
||||||
import { create } from "./MarkdownLinkRenderer";
|
import { create } from "./MarkdownLinkRenderer";
|
||||||
import {useTranslation, WithTranslation, withTranslation} from "react-i18next";
|
import { useTranslation, WithTranslation, withTranslation } from "react-i18next";
|
||||||
import Notification from "./Notification";
|
import Notification from "./Notification";
|
||||||
import { createTransformer } from "./remarkChangesetShortLinkParser";
|
import { createTransformer } from "./remarkChangesetShortLinkParser";
|
||||||
|
|
||||||
type Props = RouteComponentProps & WithTranslation & {
|
type Props = RouteComponentProps &
|
||||||
content: string;
|
WithTranslation & {
|
||||||
renderContext?: object;
|
content: string;
|
||||||
renderers?: any;
|
renderContext?: object;
|
||||||
skipHtml?: boolean;
|
renderers?: any;
|
||||||
enableAnchorHeadings?: boolean;
|
skipHtml?: boolean;
|
||||||
// basePath for markdown links
|
enableAnchorHeadings?: boolean;
|
||||||
basePath?: string;
|
// basePath for markdown links
|
||||||
|
basePath?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type State = {
|
||||||
|
contentRef: HTMLDivElement | null | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
const xmlMarkupSample = `\`\`\`xml
|
const xmlMarkupSample = `\`\`\`xml
|
||||||
@@ -73,27 +78,35 @@ const MarkdownErrorNotification: FC = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
class MarkdownView extends React.Component<Props> {
|
class MarkdownView extends React.Component<Props, State> {
|
||||||
static defaultProps: Partial<Props> = {
|
static defaultProps: Partial<Props> = {
|
||||||
enableAnchorHeadings: false,
|
enableAnchorHeadings: false,
|
||||||
skipHtml: false
|
skipHtml: false
|
||||||
};
|
};
|
||||||
|
|
||||||
contentRef: HTMLDivElement | null | undefined;
|
|
||||||
|
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
contentRef: null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldComponentUpdate(nextProps: Readonly<Props>, nextState: Readonly<State>, nextContext: any): boolean {
|
||||||
|
// We have check if the contentRef changed and update afterwards so the page can scroll to the anchor links.
|
||||||
|
// Otherwise it can happen that componentDidUpdate is never executed depending on how fast the markdown got rendered
|
||||||
|
return this.state.contentRef !== nextState.contentRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate() {
|
componentDidUpdate() {
|
||||||
|
const { contentRef } = this.state;
|
||||||
// we have to use componentDidUpdate, because we have to wait until all
|
// we have to use componentDidUpdate, because we have to wait until all
|
||||||
// children are rendered and componentDidMount is called before the
|
// children are rendered and componentDidMount is called before the
|
||||||
// markdown content was rendered.
|
// markdown content was rendered.
|
||||||
const hash = this.props.location.hash;
|
const hash = this.props.location.hash;
|
||||||
if (this.contentRef && hash) {
|
if (contentRef && hash) {
|
||||||
// we query only child elements, to avoid strange scrolling with multiple
|
// we query only child elements, to avoid strange scrolling with multiple
|
||||||
// markdown elements on one page.
|
// markdown elements on one page.
|
||||||
const element = this.contentRef.querySelector(hash);
|
const element = contentRef.querySelector(hash);
|
||||||
if (element && element.scrollIntoView) {
|
if (element && element.scrollIntoView) {
|
||||||
element.scrollIntoView();
|
element.scrollIntoView();
|
||||||
}
|
}
|
||||||
@@ -128,7 +141,7 @@ class MarkdownView extends React.Component<Props> {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ErrorBoundary fallback={MarkdownErrorNotification}>
|
<ErrorBoundary fallback={MarkdownErrorNotification}>
|
||||||
<div ref={el => (this.contentRef = el)}>
|
<div ref={el => this.setState({ contentRef: el })}>
|
||||||
<Markdown
|
<Markdown
|
||||||
className="content is-word-break"
|
className="content is-word-break"
|
||||||
skipHtml={skipHtml}
|
skipHtml={skipHtml}
|
||||||
|
|||||||
Reference in New Issue
Block a user