summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarrison Healey <harrisonmhealey@gmail.com>2016-04-22 14:52:44 -0400
committerCorey Hulen <corey@hulen.com>2016-04-22 11:52:44 -0700
commitf73daebb61311efb966afdff75034a7f9c710fbf (patch)
tree0ad2923ade2991586a6f72a90d4a5148bba61be7
parente80bf13f48a9dba6815558ded39356b1cff584d2 (diff)
downloadchat-f73daebb61311efb966afdff75034a7f9c710fbf.tar.gz
chat-f73daebb61311efb966afdff75034a7f9c710fbf.tar.bz2
chat-f73daebb61311efb966afdff75034a7f9c710fbf.zip
PLT-1236 Added special handling for markdown links within mattermost (#2763)
* Added special handling for markdown links within mattermost * Moved application of .app__body class to route components
-rw-r--r--webapp/components/channel_view.jsx5
-rw-r--r--webapp/components/permalink_view.jsx5
-rw-r--r--webapp/components/posts_view.jsx2
-rw-r--r--webapp/components/tutorial/tutorial_intro_screens.jsx7
-rw-r--r--webapp/components/tutorial/tutorial_view.jsx5
-rw-r--r--webapp/utils/markdown.jsx19
-rw-r--r--webapp/utils/text_formatting.jsx4
7 files changed, 29 insertions, 18 deletions
diff --git a/webapp/components/channel_view.jsx b/webapp/components/channel_view.jsx
index 00e1b7f35..45d0f2393 100644
--- a/webapp/components/channel_view.jsx
+++ b/webapp/components/channel_view.jsx
@@ -1,6 +1,7 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
+import $ from 'jquery';
import React from 'react';
import ChannelHeader from 'components/channel_header.jsx';
@@ -35,9 +36,13 @@ export default class ChannelView extends React.Component {
}
componentDidMount() {
ChannelStore.addChangeListener(this.updateState);
+
+ $('body').addClass('app__body');
}
componentWillUnmount() {
ChannelStore.removeChangeListener(this.updateState);
+
+ $('body').removeClass('app__body');
}
componentWillReceiveProps(nextProps) {
this.setState(this.getStateFromStores(nextProps));
diff --git a/webapp/components/permalink_view.jsx b/webapp/components/permalink_view.jsx
index 2c32d643d..07f826d57 100644
--- a/webapp/components/permalink_view.jsx
+++ b/webapp/components/permalink_view.jsx
@@ -1,6 +1,7 @@
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
+import $ from 'jquery';
import React from 'react';
import ChannelHeader from 'components/channel_header.jsx';
@@ -45,10 +46,14 @@ export default class PermalinkView extends React.Component {
componentDidMount() {
ChannelStore.addChangeListener(this.updateState);
TeamStore.addChangeListener(this.updateState);
+
+ $('body').addClass('app__body');
}
componentWillUnmount() {
ChannelStore.removeChangeListener(this.updateState);
TeamStore.removeChangeListener(this.updateState);
+
+ $('body').removeClass('app__body');
}
componentWillReceiveProps(nextProps) {
this.setState(this.getStateFromStores(nextProps));
diff --git a/webapp/components/posts_view.jsx b/webapp/components/posts_view.jsx
index 560a46e9a..be098086f 100644
--- a/webapp/components/posts_view.jsx
+++ b/webapp/components/posts_view.jsx
@@ -379,13 +379,11 @@ export default class PostsView extends React.Component {
}
window.addEventListener('resize', this.handleResize);
PreferenceStore.addChangeListener(this.updateState);
- $('body').addClass('app__body');
}
componentWillUnmount() {
window.removeEventListener('resize', this.handleResize);
this.scrollStopAction.cancel();
PreferenceStore.removeChangeListener(this.updateState);
- $('body').removeClass('app__body');
}
componentDidUpdate() {
if (this.props.postList != null) {
diff --git a/webapp/components/tutorial/tutorial_intro_screens.jsx b/webapp/components/tutorial/tutorial_intro_screens.jsx
index 8b73775e5..0358a6a65 100644
--- a/webapp/components/tutorial/tutorial_intro_screens.jsx
+++ b/webapp/components/tutorial/tutorial_intro_screens.jsx
@@ -1,7 +1,6 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
-import $ from 'jquery';
import UserStore from 'stores/user_store.jsx';
import TeamStore from 'stores/team_store.jsx';
import PreferenceStore from 'stores/preference_store.jsx';
@@ -35,12 +34,6 @@ export default class TutorialIntroScreens extends React.Component {
this.state = {currentScreen: 0};
}
- componentDidMount() {
- $('body').addClass('app__body');
- }
- componentWillUnmount() {
- $('body').removeClass('app__body');
- }
handleNext() {
if (this.state.currentScreen < 2) {
this.setState({currentScreen: this.state.currentScreen + 1});
diff --git a/webapp/components/tutorial/tutorial_view.jsx b/webapp/components/tutorial/tutorial_view.jsx
index 5f2c1a257..39e7b6816 100644
--- a/webapp/components/tutorial/tutorial_view.jsx
+++ b/webapp/components/tutorial/tutorial_view.jsx
@@ -6,6 +6,7 @@ import TutorialIntroScreens from './tutorial_intro_screens.jsx';
import ChannelStore from 'stores/channel_store.jsx';
import Constants from 'utils/constants.jsx';
+import $ from 'jquery';
import React from 'react';
export default class TutorialView extends React.Component {
@@ -20,9 +21,13 @@ export default class TutorialView extends React.Component {
}
componentDidMount() {
ChannelStore.addChangeListener(this.handleChannelChange);
+
+ $('body').addClass('app__body');
}
componentWillUnmount() {
ChannelStore.removeChangeListener(this.handleChannelChange);
+
+ $('body').removeClass('app__body');
}
handleChannelChange() {
this.setState({
diff --git a/webapp/utils/markdown.jsx b/webapp/utils/markdown.jsx
index dff425e1f..f2b5bcc39 100644
--- a/webapp/utils/markdown.jsx
+++ b/webapp/utils/markdown.jsx
@@ -2,7 +2,6 @@
// See License.txt for license information.
import * as TextFormatting from './text_formatting.jsx';
-import * as Utils from './utils.jsx';
import * as syntaxHightlighting from './syntax_hightlighting.jsx';
import marked from 'marked';
@@ -137,18 +136,20 @@ class MattermostMarkdownRenderer extends marked.Renderer {
outHref = `http://${outHref}`;
}
- let output = '<a class="theme markdown__link" href="' + outHref + '"';
- if (title) {
- output += ' title="' + title + '"';
- }
+ let output = '<a class="theme markdown__link" ';
- if (outHref.lastIndexOf(Utils.getTeamURLFromAddressBar(), 0) === 0) {
- output += '>';
+ // special case for links that are inside the app
+ if (outHref.startsWith(global.location.origin)) {
+ output += 'data-link="' + outHref.substring(global.location.origin.length) + '"';
} else {
- output += ' target="_blank">';
+ output += 'href="' + outHref + '"';
+ }
+
+ if (title) {
+ output += ' title="' + title + '"';
}
- output += outText + '</a>';
+ output += '>' + outText + '</a>';
return prefix + output + suffix;
}
diff --git a/webapp/utils/text_formatting.jsx b/webapp/utils/text_formatting.jsx
index 4c8b5e24c..3aa82ccdc 100644
--- a/webapp/utils/text_formatting.jsx
+++ b/webapp/utils/text_formatting.jsx
@@ -2,6 +2,7 @@
// See License.txt for license information.
import Autolinker from 'autolinker';
+import {browserHistory} from 'react-router';
import Constants from './constants.jsx';
import * as Emoticons from './emoticons.jsx';
import * as Markdown from './markdown.jsx';
@@ -398,10 +399,13 @@ function replaceNewlines(text) {
export function handleClick(e) {
const mentionAttribute = e.target.getAttributeNode('data-mention');
const hashtagAttribute = e.target.getAttributeNode('data-hashtag');
+ const linkAttribute = e.target.getAttributeNode('data-link');
if (mentionAttribute) {
Utils.searchForTerm(mentionAttribute.value);
} else if (hashtagAttribute) {
Utils.searchForTerm(hashtagAttribute.value);
+ } else if (linkAttribute) {
+ browserHistory.push(linkAttribute.value);
}
}