1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-08-17 14:37:58 +00:00
seahub/frontend/src/components/wiki-markdown-viewer.js

138 lines
4.4 KiB
JavaScript
Raw Normal View History

2019-01-15 11:58:25 +00:00
import React from 'react';
import PropTypes from 'prop-types';
2023-12-08 03:20:12 +00:00
import { EXTERNAL_EVENTS, EventBus, MarkdownViewer } from '@seafile/seafile-editor';
import { gettext, isPublicWiki, mediaUrl, repoID, serviceURL, sharedToken, slug } from '../utils/constants';
2019-01-15 11:58:25 +00:00
import Loading from './loading';
import { Utils } from '../utils/utils';
2019-01-15 11:58:25 +00:00
const propTypes = {
children: PropTypes.object,
isFileLoading: PropTypes.bool.isRequired,
markdownContent: PropTypes.string.isRequired,
latestContributor: PropTypes.string.isRequired,
lastModified: PropTypes.string.isRequired,
2019-01-24 07:41:01 +00:00
onLinkClick: PropTypes.func.isRequired,
isWiki: PropTypes.bool,
isTOCShow: PropTypes.bool,
2019-04-08 05:32:46 +00:00
// for dir-column-file component(import repoID is undefined)
repoID: PropTypes.string,
path: PropTypes.string,
2019-01-15 11:58:25 +00:00
};
const contentClass = 'wiki-page-content';
2019-01-15 11:58:25 +00:00
class WikiMarkdownViewer extends React.Component {
constructor(props) {
super(props);
2023-12-08 03:20:12 +00:00
this.scrollRef = React.createRef();
2019-01-15 11:58:25 +00:00
}
2019-01-22 07:58:28 +00:00
componentDidMount() {
2023-12-08 03:20:12 +00:00
const eventBus = EventBus.getInstance();
this.unsubscribeLinkClick = eventBus.subscribe(EXTERNAL_EVENTS.ON_LINK_CLICK, this.onLinkClick);
2019-01-22 07:58:28 +00:00
}
2019-01-15 11:58:25 +00:00
componentWillUnmount() {
2023-12-08 03:20:12 +00:00
this.unsubscribeLinkClick();
2019-01-15 11:58:25 +00:00
}
onLinkClick = (event) => {
event.preventDefault();
2019-01-22 07:58:28 +00:00
event.stopPropagation();
2019-01-15 11:58:25 +00:00
let link = '';
2023-12-08 03:20:12 +00:00
let target = event.target;
while (!target.dataset || !target.dataset.url) {
target = target.parentNode;
2019-01-15 11:58:25 +00:00
}
2023-12-08 03:20:12 +00:00
if (!target) return;
link = target.dataset.url;
2019-01-15 11:58:25 +00:00
this.props.onLinkClick(link);
};
2019-01-15 11:58:25 +00:00
2019-01-24 07:41:01 +00:00
changeInlineNode = (item) => {
2021-04-27 03:22:55 +00:00
let url, imagePath;
2021-04-27 03:28:12 +00:00
if (item.type == 'image' && isPublicWiki) { // change image url
2021-04-27 03:22:55 +00:00
url = item.data.src;
const re = new RegExp(serviceURL + '/lib/' + repoID +'/file.*raw=1');
// different repo
if (re.test(url)) {
// get image path
let index = url.indexOf('/file');
let index2 = url.indexOf('?');
imagePath = url.substring(index + 5, index2);
} else if (/^\.\.\/*/.test(url) || /^\.\/*/.test(url)) {
const path = this.props.path;
const originalPath = path.slice(0, path.lastIndexOf('/')) + '/' + url;
imagePath = Utils.pathNormalize(originalPath);
} else {
return;
}
2021-04-27 03:22:55 +00:00
item.data.src = serviceURL + '/view-image-via-public-wiki/?slug=' + slug + '&path=' + imagePath;
2021-04-27 03:28:12 +00:00
} else if (item.type == 'link') { // change link url
2023-12-08 03:20:12 +00:00
url = item.url;
2021-04-27 03:22:55 +00:00
if (Utils.isInternalFileLink(url, repoID)) { // change file url
if (Utils.isInternalMarkdownLink(url, repoID)) {
let path = Utils.getPathFromInternalMarkdownLink(url, repoID);
2019-01-24 07:41:01 +00:00
// replace url
2023-12-08 03:20:12 +00:00
item.url = serviceURL + '/published/' + slug + path;
2021-04-27 03:22:55 +00:00
} else {
2023-12-08 03:20:12 +00:00
item.url = url.replace(/(.*)lib\/([-0-9a-f]{36})\/file(.*)/g, (match, p1, p2, p3) => {
2021-04-27 03:22:55 +00:00
return `${p1}d/${sharedToken}/files/?p=${p3}&dl=1`;
});
}
2021-04-27 03:22:55 +00:00
} else if (Utils.isInternalDirLink(url, repoID)) { // change dir url
let path = Utils.getPathFromInternalDirLink(url, repoID);
// replace url
2023-12-08 03:20:12 +00:00
item.url = serviceURL + '/published/' + slug + path;
2019-01-24 07:41:01 +00:00
}
}
return item;
};
2019-01-24 07:41:01 +00:00
modifyValueBeforeRender = (value) => {
let newNodes = Utils.changeMarkdownNodes(value, this.changeInlineNode);
return newNodes;
};
2019-01-24 07:41:01 +00:00
renderMarkdown = () => {
2023-12-08 03:20:12 +00:00
const { isTOCShow = true, isWiki, markdownContent } = this.props;
const props = {
isShowOutline: isTOCShow,
mathJaxSource: `${mediaUrl}js/mathjax/tex-svg.js`,
value: markdownContent,
scrollRef: this.scrollRef,
...(isWiki && {beforeRenderCallback: this.modifyValueBeforeRender})
};
2019-01-24 07:41:01 +00:00
2023-12-08 03:20:12 +00:00
return <MarkdownViewer {...props} />;
};
2019-01-24 07:41:01 +00:00
2019-01-15 11:58:25 +00:00
render() {
if (this.props.isFileLoading) {
return <Loading />;
2019-01-15 11:58:25 +00:00
}
2019-05-29 03:48:00 +00:00
// In dir-column-file repoID is one of props, width is 100%; In wiki-viewer repoID is not props, width isn't 100%
2019-06-04 09:59:54 +00:00
let contentClassName = `${this.props.repoID ? contentClass + ' w-100' : contentClass}`;
2019-01-15 11:58:25 +00:00
return (
2023-12-08 03:20:12 +00:00
<div ref={this.scrollRef} className="wiki-page-container">
2019-05-29 03:48:00 +00:00
<div className={contentClassName}>
2019-01-15 11:58:25 +00:00
{this.props.children}
2019-01-24 07:41:01 +00:00
{this.renderMarkdown()}
2019-01-15 11:58:25 +00:00
<p id="wiki-page-last-modified">{gettext('Last modified by')} {this.props.latestContributor}, <span>{this.props.lastModified}</span></p>
</div>
</div>
);
}
}
2019-01-24 07:41:01 +00:00
const defaultProps = {
isWiki: false,
};
2019-01-24 07:41:01 +00:00
2019-01-15 11:58:25 +00:00
WikiMarkdownViewer.propTypes = propTypes;
2019-01-24 07:41:01 +00:00
MarkdownViewer.defaultProps = defaultProps;
2019-01-15 11:58:25 +00:00
export default WikiMarkdownViewer;