diff --git a/web/react/components/user_settings/code_theme_chooser.jsx b/web/react/components/user_settings/code_theme_chooser.jsx
new file mode 100644
index 0000000000..eef4b24bae
--- /dev/null
+++ b/web/react/components/user_settings/code_theme_chooser.jsx
@@ -0,0 +1,55 @@
+// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+var Constants = require('../../utils/constants.jsx');
+
+export default class CodeThemeChooser extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {};
+ }
+ render() {
+ const theme = this.props.theme;
+
+ const premadeThemes = [];
+ for (const k in Constants.CODE_THEMES) {
+ if (Constants.CODE_THEMES.hasOwnProperty(k)) {
+ let activeClass = '';
+ if (k === theme.codeTheme) {
+ activeClass = 'active';
+ }
+
+ premadeThemes.push(
+
+
this.props.updateTheme(k)}
+ >
+
+
+
+ );
+ }
+ }
+
+ return (
+
+ {premadeThemes}
+
+ );
+ }
+}
+
+CodeThemeChooser.propTypes = {
+ theme: React.PropTypes.object.isRequired,
+ updateTheme: React.PropTypes.func.isRequired
+};
diff --git a/web/react/components/user_settings/custom_theme_chooser.jsx b/web/react/components/user_settings/custom_theme_chooser.jsx
index 44b3f45448..095e5b6226 100644
--- a/web/react/components/user_settings/custom_theme_chooser.jsx
+++ b/web/react/components/user_settings/custom_theme_chooser.jsx
@@ -40,11 +40,12 @@ export default class CustomThemeChooser extends React.Component {
const theme = {type: 'custom'};
let index = 0;
Constants.THEME_ELEMENTS.forEach((element) => {
- if (index < colors.length) {
+ if (index < colors.length - 1) {
theme[element.id] = colors[index];
}
index++;
});
+ theme.codeTheme = colors[colors.length - 1];
this.props.updateTheme(theme);
}
@@ -78,6 +79,8 @@ export default class CustomThemeChooser extends React.Component {
colors += theme[element.id] + ',';
});
+ colors += theme.codeTheme;
+
const pasteBox = (
{custom}
- {serverError}
+ {'Code Theme'}
+
+
+ {serverError}
' + TextFormatting.sanitizeHtml($(parsed).text()) + '';
+ }
+
+ let parsed = highlightJs.highlight(usedLanguage, code);
+ return '' +
+ '' + HighlightedLanguages[usedLanguage] + '' +
+ '' + parsed.value + '' +
+ '
';
}
br() {
diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx
index 35ce49ae20..c7c8549b99 100644
--- a/web/react/utils/utils.jsx
+++ b/web/react/utils/utils.jsx
@@ -424,6 +424,11 @@ export function toTitleCase(str) {
}
export function applyTheme(theme) {
+ if (!theme.codeTheme) {
+ theme.codeTheme = Constants.DEFAULT_CODE_THEME;
+ }
+ updateCodeTheme(theme.codeTheme);
+
if (theme.sidebarBg) {
changeCss('.sidebar--left, .settings-modal .settings-table .settings-links, .sidebar--menu', 'background:' + theme.sidebarBg, 1);
}
@@ -612,6 +617,27 @@ export function rgb2hex(rgbIn) {
return '#' + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}
+export function updateCodeTheme(theme) {
+ const path = '/static/css/highlight/' + theme + '.css';
+ const $link = $('link.code_theme');
+ if (path !== $link.attr('href')) {
+ changeCss('code.hljs', 'visibility: hidden');
+ var xmlHTTP = new XMLHttpRequest();
+ xmlHTTP.open('GET', path, true);
+ xmlHTTP.onload = function onLoad() {
+ $link.attr('href', path);
+ if (isBrowserFirefox()) {
+ $link.one('load', () => {
+ changeCss('code.hljs', 'visibility: visible');
+ });
+ } else {
+ changeCss('code.hljs', 'visibility: visible');
+ }
+ };
+ xmlHTTP.send();
+ }
+}
+
export function placeCaretAtEnd(el) {
el.focus();
if (typeof window.getSelection != 'undefined' && typeof document.createRange != 'undefined') {
diff --git a/web/sass-files/sass/partials/_post.scss b/web/sass-files/sass/partials/_post.scss
index 11816efd98..7709e17f32 100644
--- a/web/sass-files/sass/partials/_post.scss
+++ b/web/sass-files/sass/partials/_post.scss
@@ -473,6 +473,22 @@ body.ios {
white-space: nowrap;
cursor: pointer;
}
+ .post-body--code {
+ font-size: .97em;
+ position:relative;
+ .post-body--code__language {
+ position: absolute;
+ right: 0;
+ background: #fff;
+ cursor: default;
+ padding: 0.3em 0.5em 0.1em;
+ border-bottom-left-radius: 4px;
+ @include opacity(.3);
+ }
+ code {
+ white-space: pre;
+ }
+ }
}
.create-reply-form-wrap {
width: 100%;
diff --git a/web/static/css/highlight b/web/static/css/highlight
new file mode 120000
index 0000000000..c774cf3974
--- /dev/null
+++ b/web/static/css/highlight
@@ -0,0 +1 @@
+../../react/node_modules/highlight.js/styles/
\ No newline at end of file
diff --git a/web/static/images/themes/code_themes/github.png b/web/static/images/themes/code_themes/github.png
new file mode 100644
index 0000000000..d0538d6c0b
Binary files /dev/null and b/web/static/images/themes/code_themes/github.png differ
diff --git a/web/static/images/themes/code_themes/monokai.png b/web/static/images/themes/code_themes/monokai.png
new file mode 100644
index 0000000000..8f92d2a18d
Binary files /dev/null and b/web/static/images/themes/code_themes/monokai.png differ
diff --git a/web/static/images/themes/code_themes/solarized_dark.png b/web/static/images/themes/code_themes/solarized_dark.png
new file mode 100644
index 0000000000..76055c6782
Binary files /dev/null and b/web/static/images/themes/code_themes/solarized_dark.png differ
diff --git a/web/static/images/themes/code_themes/solarized_light.png b/web/static/images/themes/code_themes/solarized_light.png
new file mode 100644
index 0000000000..b9595c22d7
Binary files /dev/null and b/web/static/images/themes/code_themes/solarized_light.png differ
diff --git a/web/templates/head.html b/web/templates/head.html
index 041831ed7a..fdc371af4a 100644
--- a/web/templates/head.html
+++ b/web/templates/head.html
@@ -24,6 +24,7 @@
+