From 529513606b74fce60cbb066b381b27fbb6ea9d52 Mon Sep 17 00:00:00 2001 From: Rodrigo Corsi Date: Tue, 8 Mar 2016 09:38:09 -0300 Subject: Created component CodePreview --- webapp/components/code_preview.jsx | 101 +++++++++++++++++ webapp/components/view_image.jsx | 11 ++ webapp/sass/components/_files.scss | 1 + webapp/sass/components/_modal.scss | 16 ++- webapp/sass/layout/_markdown.scss | 48 +++++++-- webapp/utils/constants.jsx | 82 +++++++++----- webapp/utils/markdown.jsx | 87 ++------------- webapp/utils/syntax_hightlighting.jsx | 197 ++++++++++++++++++++++++++++++++++ webapp/utils/utils.jsx | 2 +- 9 files changed, 434 insertions(+), 111 deletions(-) create mode 100644 webapp/components/code_preview.jsx create mode 100644 webapp/utils/syntax_hightlighting.jsx diff --git a/webapp/components/code_preview.jsx b/webapp/components/code_preview.jsx new file mode 100644 index 000000000..8d2bc6269 --- /dev/null +++ b/webapp/components/code_preview.jsx @@ -0,0 +1,101 @@ +// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import $ from 'jquery'; +import * as syntaxHightlighting from 'utils/syntax_hightlighting.jsx'; +import Constants from 'utils/constants.jsx'; +import FileInfoPreview from './file_info_preview.jsx'; + +import React from 'react'; + +export default class CodePreview extends React.Component { + constructor(props) { + super(props); + + this.updateStateFromProps = this.updateStateFromProps.bind(this); + this.handleReceivedError = this.handleReceivedError.bind(this); + this.handleReceivedCode = this.handleReceivedCode.bind(this); + + this.state = { + code: '', + lang: '', + loading: true, + success: true + }; + } + + componentDidMount() { + this.updateStateFromProps(this.props); + } + + componentWillReceiveProps(nextProps) { + if (this.props.fileUrl !== nextProps.fileUrl) { + this.updateStateFromProps(nextProps); + } + } + + updateStateFromProps(props) { + var usedLanguage = syntaxHightlighting.getLang(props.filename); + + if (!usedLanguage || props.fileInfo.size > Constants.CODE_PREVIEW_MAX_FILE_SIZE) { + this.setState({code: '', lang: '', loading: false, success: false}); + return; + } + + this.setState({code: '', lang: usedLanguage, loading: true}); + + $.ajax({ + async: true, + url: props.fileUrl, + type: 'GET', + error: this.handleReceivedError, + success: this.handleReceivedCode + }); + } + + handleReceivedCode(data) { + const parsed = syntaxHightlighting.formatCode(this.state.lang, data, this.props.filename) + this.setState({code: parsed, loading: false, success: true}); + } + + handleReceivedError() { + this.setState({loading: false, success: false}); + } + + static support(filename) { + return typeof syntaxHightlighting.getLang(filename) !== 'undefined'; + } + + render() { + if (this.state.loading) { + return ( +
+ +
+ ); + } + + if (!this.state.success) { + return ( + + ); + } + + return
; + } +} + +CodePreview.propTypes = { + filename: React.PropTypes.string.isRequired, + fileUrl: React.PropTypes.string.isRequired, + fileInfo: React.PropTypes.object.isRequired, + formatMessage: React.PropTypes.func.isRequired +}; diff --git a/webapp/components/view_image.jsx b/webapp/components/view_image.jsx index 2b7e03382..7572f88ae 100644 --- a/webapp/components/view_image.jsx +++ b/webapp/components/view_image.jsx @@ -7,6 +7,7 @@ import * as Client from 'utils/client.jsx'; import * as Utils from 'utils/utils.jsx'; import AudioVideoPreview from './audio_video_preview.jsx'; import Constants from 'utils/constants.jsx'; +import CodePreview from './code_preview.jsx'; import FileInfoPreview from './file_info_preview.jsx'; import FileStore from 'stores/file_store.jsx'; import ViewImagePopoverBar from './view_image_popover_bar.jsx'; @@ -254,6 +255,15 @@ class ViewImageModal extends React.Component { formatMessage={this.props.intl.formatMessage} /> ); + } else if (CodePreview.support(filename)) { + content = ( + + ); } else { content = (
e.stopPropagation()} diff --git a/webapp/sass/components/_files.scss b/webapp/sass/components/_files.scss index b854312c1..5522c6db8 100644 --- a/webapp/sass/components/_files.scss +++ b/webapp/sass/components/_files.scss @@ -234,6 +234,7 @@ .file-details__container { @include display-flex; + background: $white; .file-details { height: 270px; diff --git a/webapp/sass/components/_modal.scss b/webapp/sass/components/_modal.scss index 601aa33ab..94378aabe 100644 --- a/webapp/sass/components/_modal.scss +++ b/webapp/sass/components/_modal.scss @@ -256,13 +256,27 @@ } > div { - background: $white; display: inline-block; min-height: 100px; min-width: 320px; position: relative; } + code { + min-height: 130px; + min-width: 330px; + } + + pre, code { + display: inline-block; + } + + .post-body--code { + max-height: calc(100vh - 80px); + max-width: calc(100vw - 80px); + overflow: auto; + } + img { max-height: 100%; max-width: 100%; diff --git a/webapp/sass/layout/_markdown.scss b/webapp/sass/layout/_markdown.scss index e2180c64d..b9acd8b5b 100644 --- a/webapp/sass/layout/_markdown.scss +++ b/webapp/sass/layout/_markdown.scss @@ -22,29 +22,63 @@ } .post-body--code { + overflow-x: auto; + overflow-y: hidden; position: relative; pre { - margin-bottom: 0; - overflow: auto; - word-break: normal; - word-wrap: normal; + border: 1px solid rgba(221,221,221,0.2); + border-radius: .25em; + margin: 0; + padding: 0px; + text-align: left; + white-space: nowrap; + } + + code { + border: none; + white-space: pre; + } + + td { + padding: 0 .5em; + vertical-align: top; + } + + &:hover .post-body--code__language { + @include opacity(1); } } .post-body--code__language { + @include opacity(0); @include translate3d(0, 0, 0); background: #21586d; + border-radius: 0 .25em; color: $white; - font-size: 13px; - opacity: .7; padding: 4px 10px 5px; position: absolute; right: 0; top: 0; + -webkit-transition: opacity 0.6s; + -moz-transition: opacity 0.6s; + -o-transition: opacity 0.6s; + transition: opacity 0.6s; z-index: 5; } +.post-body--code__lineno { + border-right: 1px solid #aaa; + color: #aaa; + margin-right: .5em; + text-align: right; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + -o-user-select: none; + user-select: none; +} + .post__body { hr { @include opacity(.2); @@ -108,9 +142,9 @@ blockquote { } pre { - border: none; color: inherit; margin: 5px 0; + padding: 0; } code { diff --git a/webapp/utils/constants.jsx b/webapp/utils/constants.jsx index c1e527702..29178aca6 100644 --- a/webapp/utils/constants.jsx +++ b/webapp/utils/constants.jsx @@ -144,7 +144,7 @@ export default { PRESENTATION_TYPES: ['ppt', 'pptx'], SPREADSHEET_TYPES: ['xlsx', 'csv'], WORD_TYPES: ['doc', 'docx'], - CODE_TYPES: ['css', 'html', 'js', 'php', 'rb'], + CODE_TYPES: ['as', 'applescript', 'osascript', 'scpt', 'bash', 'sh', 'zsh', 'clj', 'boot', 'cl2', 'cljc', 'cljs', 'cljs.hl', 'cljscm', 'cljx', 'hic', 'coffee', '_coffee', 'cake', 'cjsx', 'cson', 'iced', 'cpp', 'c', 'cc', 'h', 'c++', 'h++', 'hpp', 'cs', 'csharp', 'css', 'd', 'di', 'dart', 'delphi', 'dpr', 'dfm', 'pas', 'pascal', 'freepascal', 'lazarus', 'lpr', 'lfm', 'diff', 'django', 'jinja', 'dockerfile', 'docker', 'erl', 'f90', 'f95', 'fsharp', 'fs', 'gcode', 'nc', 'go', 'groovy', 'handlebars', 'hbs', 'html.hbs', 'html.handlebars', 'hs', 'hx', 'java', 'jsp', 'js', 'jsx', 'json', 'jl', 'kt', 'ktm', 'kts', 'less', 'lisp', 'lua', 'mk', 'mak', 'md', 'mkdown', 'mkd', 'matlab', 'm', 'mm', 'objc', 'obj-c', 'ml', 'perl', 'pl', 'php', 'php3', 'php4', 'php5', 'php6', 'ps', 'ps1', 'pp', 'py', 'gyp', 'r', 'ruby', 'rb', 'gemspec', 'podspec', 'thor', 'irb', 'rs', 'scala', 'scm', 'sld', 'scss', 'st', 'sql', 'swift', 'tex', 'vbnet', 'vb', 'bas', 'vbs', 'v', 'veo', 'xml', 'html', 'xhtml', 'rss', 'atom', 'xsl', 'plist', 'yaml'], PDF_TYPES: ['pdf'], PATCH_TYPES: ['patch'], ICON_FROM_TYPE: { @@ -514,30 +514,64 @@ export default { SPACE: 32, TAB: 9 }, + CODE_PREVIEW_MAX_FILE_SIZE: 500000, // 500 KB HighlightedLanguages: { - diff: 'Diff', - apache: 'Apache', - makefile: 'Makefile', - http: 'HTTP', - json: 'JSON', - markdown: 'Markdown', - javascript: 'JavaScript', - css: 'CSS', - nginx: 'nginx', - objectivec: 'Objective-C', - python: 'Python', - xml: 'XML', - perl: 'Perl', - bash: 'Bash', - php: 'PHP', - coffeescript: 'CoffeeScript', - cs: 'C#', - cpp: 'C++', - sql: 'SQL', - go: 'Go', - ruby: 'Ruby', - java: 'Java', - ini: 'ini' + actionscript: {name: 'ActionScript', extensions: ['as']}, + applescript: {name: 'AppleScript', extensions: ['applescript', 'osascript', 'scpt']}, + bash: {name: 'Bash', extensions: ['bash', 'sh', 'zsh']}, + clojure: {name: 'Clojure', extensions: ['clj', 'boot', 'cl2', 'cljc', 'cljs', 'cljs.hl', 'cljscm', 'cljx', 'hic']}, + coffeescript: {name: 'CoffeeScript', extensions: ['coffee', '_coffee', 'cake', 'cjsx', 'cson', 'iced']}, + cpp: {name: 'C/C++', extensions: ['cpp', 'c', 'cc', 'h', 'c++', 'h++', 'hpp']}, + cs: {name: 'C#', extensions: ['cs', 'csharp']}, + css: {name: 'CSS', extensions: ['css']}, + d: {name: 'D', extensions: ['d', 'di']}, + dart: {name: 'Dart', extensions: ['dart']}, + delphi: {name: 'Delphi', extensions: ['delphi', 'dpr', 'dfm', 'pas', 'pascal', 'freepascal', 'lazarus', 'lpr', 'lfm']}, + diff: {name: 'Diff', extensions: ['diff', 'patch']}, + django: {name: 'Django', extensions: ['django', 'jinja']}, + dockerfile: {name: 'Dockerfile', extensions: ['dockerfile', 'docker']}, + erlang: {name: 'Erlang', extensions: ['erl']}, + fortran: {name: 'Fortran', extensions: ['f90', 'f95']}, + fsharp: {name: 'F#', extensions: ['fsharp', 'fs']}, + gcode: {name: 'G-Code', extensions: ['gcode', 'nc']}, + go: {name: 'Go', extensions: ['go']}, + groovy: {name: 'Groovy', extensions: ['groovy']}, + handlebars: {name: 'Handlebars', extensions: ['handlebars', 'hbs', 'html.hbs', 'html.handlebars']}, + haskell: {name: 'Haskell', extensions: ['hs']}, + haxe: {name: 'Haxe', extensions: ['hx']}, + java: {name: 'Java', extensions: ['java', 'jsp']}, + javascript: {name: 'JavaScript', extensions: ['js', 'jsx']}, + json: {name: 'JSON', extensions: ['json']}, + julia: {name: 'Julia', extensions: ['jl']}, + kotlin: {name: 'Kotlin', extensions: ['kt', 'ktm', 'kts']}, + less: {name: 'Less', extensions: ['less']}, + lisp: {name: 'Lisp', extensions: ['lisp']}, + lua: {name: 'Lua', extensions: ['lua']}, + makefile: {name: 'Makefile', extensions: ['mk', 'mak']}, + markdown: {name: 'Markdown', extensions: ['md', 'mkdown', 'mkd']}, + matlab: {name: 'Matlab', extensions: ['matlab', 'm']}, + objectivec: {name: 'Objective C', extensions: ['mm', 'objc', 'obj-c']}, + ocaml: {name: 'OCaml', extensions: ['ml']}, + perl: {name: 'Perl', extensions: ['perl', 'pl']}, + php: {name: 'PHP', extensions: ['php', 'php3', 'php4', 'php5', 'php6']}, + powershell: {name: 'PowerShell', extensions: ['ps', 'ps1']}, + puppet: {name: 'Puppet', extensions: ['pp']}, + python: {name: 'Python', extensions: ['py', 'gyp']}, + r: {name: 'R', extensions: ['r']}, + ruby: {name: 'Ruby', extensions: ['ruby', 'rb', 'gemspec', 'podspec', 'thor', 'irb']}, + rust: {name: 'Rust', extensions: ['rs']}, + scala: {name: 'Scala', extensions: ['scala']}, + scheme: {name: 'Scheme', extensions: ['scm', 'sld']}, + scss: {name: 'SCSS', extensions: ['scss']}, + smalltalk: {name: 'Smalltalk', extensions: ['st']}, + sql: {name: 'SQL', extensions: ['sql']}, + swift: {name: 'Swift', extensions: ['swift']}, + tex: {name: 'TeX', extensions: ['tex']}, + vbnet: {name: 'VB.Net', extensions: ['vbnet', 'vb', 'bas']}, + vbscript: {name: 'VBScript', extensions: ['vbs']}, + verilog: {name: 'Verilog', extensions: ['v', 'veo']}, + xml: {name: 'HTML, XML', extensions: ['xml', 'html', 'xhtml', 'rss', 'atom', 'xsl', 'plist']}, + yaml: {name: 'YAML', extensions: ['yaml']} }, PostsViewJumpTypes: { BOTTOM: 1, diff --git a/webapp/utils/markdown.jsx b/webapp/utils/markdown.jsx index 635a39290..ee63e6a19 100644 --- a/webapp/utils/markdown.jsx +++ b/webapp/utils/markdown.jsx @@ -1,57 +1,9 @@ // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -import highlightJs from 'highlight.js/lib/highlight.js'; -import highlightJsDiff from 'highlight.js/lib/languages/diff.js'; -import highlightJsApache from 'highlight.js/lib/languages/apache.js'; -import highlightJsMakefile from 'highlight.js/lib/languages/makefile.js'; -import highlightJsHttp from 'highlight.js/lib/languages/http.js'; -import highlightJsJson from 'highlight.js/lib/languages/json.js'; -import highlightJsMarkdown from 'highlight.js/lib/languages/markdown.js'; -import highlightJsJavascript from 'highlight.js/lib/languages/javascript.js'; -import highlightJsCss from 'highlight.js/lib/languages/css.js'; -import highlightJsNginx from 'highlight.js/lib/languages/nginx.js'; -import highlightJsObjectivec from 'highlight.js/lib/languages/objectivec.js'; -import highlightJsPython from 'highlight.js/lib/languages/python.js'; -import highlightJsXml from 'highlight.js/lib/languages/xml.js'; -import highlightJsPerl from 'highlight.js/lib/languages/perl.js'; -import highlightJsBash from 'highlight.js/lib/languages/bash.js'; -import highlightJsPhp from 'highlight.js/lib/languages/php.js'; -import highlightJsCoffeescript from 'highlight.js/lib/languages/coffeescript.js'; -import highlightJsCs from 'highlight.js/lib/languages/cs.js'; -import highlightJsCpp from 'highlight.js/lib/languages/cpp.js'; -import highlightJsSql from 'highlight.js/lib/languages/sql.js'; -import highlightJsGo from 'highlight.js/lib/languages/go.js'; -import highlightJsRuby from 'highlight.js/lib/languages/ruby.js'; -import highlightJsJava from 'highlight.js/lib/languages/java.js'; -import highlightJsIni from 'highlight.js/lib/languages/ini.js'; - -highlightJs.registerLanguage('diff', highlightJsDiff); -highlightJs.registerLanguage('apache', highlightJsApache); -highlightJs.registerLanguage('makefile', highlightJsMakefile); -highlightJs.registerLanguage('http', highlightJsHttp); -highlightJs.registerLanguage('json', highlightJsJson); -highlightJs.registerLanguage('markdown', highlightJsMarkdown); -highlightJs.registerLanguage('javascript', highlightJsJavascript); -highlightJs.registerLanguage('css', highlightJsCss); -highlightJs.registerLanguage('nginx', highlightJsNginx); -highlightJs.registerLanguage('objectivec', highlightJsObjectivec); -highlightJs.registerLanguage('python', highlightJsPython); -highlightJs.registerLanguage('xml', highlightJsXml); -highlightJs.registerLanguage('perl', highlightJsPerl); -highlightJs.registerLanguage('bash', highlightJsBash); -highlightJs.registerLanguage('php', highlightJsPhp); -highlightJs.registerLanguage('coffeescript', highlightJsCoffeescript); -highlightJs.registerLanguage('cs', highlightJsCs); -highlightJs.registerLanguage('cpp', highlightJsCpp); -highlightJs.registerLanguage('sql', highlightJsSql); -highlightJs.registerLanguage('go', highlightJsGo); -highlightJs.registerLanguage('ruby', highlightJsRuby); -highlightJs.registerLanguage('java', highlightJsJava); -highlightJs.registerLanguage('ini', highlightJsIni); - import * as TextFormatting from './text_formatting.jsx'; import * as Utils from './utils.jsx'; +import * as syntaxHightlighting from './syntax_hightlighting.jsx'; import marked from 'marked'; import katex from 'katex'; @@ -110,31 +62,11 @@ class MattermostMarkdownRenderer extends marked.Renderer { this.formattingOptions = formattingOptions; } - code(code, language, escaped) { + code(code, language) { let usedLanguage = language || ''; usedLanguage = usedLanguage.toLowerCase(); - // treat html as xml to prevent injection attacks - if (usedLanguage === 'html') { - usedLanguage = 'xml'; - } - - if (HighlightedLanguages[usedLanguage]) { - const parsed = highlightJs.highlight(usedLanguage, code); - - return ( - '
' + - '' + - HighlightedLanguages[usedLanguage] + - '' + - '
' +
-                        '' +
-                            parsed.value +
-                        '' +
-                    '
' + - '
' - ); - } else if (usedLanguage === 'tex' || usedLanguage === 'latex') { + if (usedLanguage === 'tex' || usedLanguage === 'latex') { try { const html = katex.renderToString(code, {throwOnError: false, displayMode: true}); @@ -144,13 +76,12 @@ class MattermostMarkdownRenderer extends marked.Renderer { } } - return ( - '
' +
-                '' +
-                    (escaped ? code : TextFormatting.sanitizeHtml(code)) + '\n' +
-                '' +
-            '
' - ); + // treat html as xml to prevent injection attacks + if (usedLanguage === 'html') { + usedLanguage = 'xml'; + } + + return syntaxHightlighting.formatCode(usedLanguage, code); } codespan(text) { diff --git a/webapp/utils/syntax_hightlighting.jsx b/webapp/utils/syntax_hightlighting.jsx new file mode 100644 index 000000000..981ce6b35 --- /dev/null +++ b/webapp/utils/syntax_hightlighting.jsx @@ -0,0 +1,197 @@ +// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import * as Utils from './utils.jsx'; +import * as TextFormatting from './text_formatting.jsx'; +import Constants from './constants.jsx'; + +import hlJS from 'highlight.js/lib/highlight.js'; + +import hljsActionscript from 'highlight.js/lib/languages/actionscript.js'; +import hljsApplescript from 'highlight.js/lib/languages/applescript.js'; +import hljsBash from 'highlight.js/lib/languages/bash.js'; +import hljsClojure from 'highlight.js/lib/languages/clojure.js'; +import hljsCoffeescript from 'highlight.js/lib/languages/coffeescript.js'; +import hljsCpp from 'highlight.js/lib/languages/cpp.js'; +import hljsCs from 'highlight.js/lib/languages/cs.js'; +import hljsCss from 'highlight.js/lib/languages/css.js'; +import hljsD from 'highlight.js/lib/languages/d.js'; +import hljsDart from 'highlight.js/lib/languages/dart.js'; +import hljsDelphi from 'highlight.js/lib/languages/delphi.js'; +import hljsDiff from 'highlight.js/lib/languages/diff.js'; +import hljsDjango from 'highlight.js/lib/languages/django.js'; +import hljsDockerfile from 'highlight.js/lib/languages/dockerfile.js'; +import hljsErlang from 'highlight.js/lib/languages/erlang.js'; +import hljsFortran from 'highlight.js/lib/languages/fortran.js'; +import hljsFsharp from 'highlight.js/lib/languages/fsharp.js'; +import hljsGcode from 'highlight.js/lib/languages/gcode.js'; +import hljsGo from 'highlight.js/lib/languages/go.js'; +import hljsGroovy from 'highlight.js/lib/languages/groovy.js'; +import hljsHandlebars from 'highlight.js/lib/languages/handlebars.js'; +import hljsHaskell from 'highlight.js/lib/languages/haskell.js'; +import hljsHaxe from 'highlight.js/lib/languages/haxe.js'; +import hljsJava from 'highlight.js/lib/languages/java.js'; +import hljsJavascript from 'highlight.js/lib/languages/javascript.js'; +import hljsJson from 'highlight.js/lib/languages/json.js'; +import hljsJulia from 'highlight.js/lib/languages/julia.js'; +import hljsKotlin from 'highlight.js/lib/languages/kotlin.js'; +import hljsLess from 'highlight.js/lib/languages/less.js'; +import hljsLisp from 'highlight.js/lib/languages/lisp.js'; +import hljsLua from 'highlight.js/lib/languages/lua.js'; +import hljsMakefile from 'highlight.js/lib/languages/makefile.js'; +import hljsMarkdown from 'highlight.js/lib/languages/markdown.js'; +import hljsMatlab from 'highlight.js/lib/languages/matlab.js'; +import hljsObjectivec from 'highlight.js/lib/languages/objectivec.js'; +import hljsOcaml from 'highlight.js/lib/languages/ocaml.js'; +import hljsPerl from 'highlight.js/lib/languages/perl.js'; +import hljsPhp from 'highlight.js/lib/languages/php.js'; +import hljsPowershell from 'highlight.js/lib/languages/powershell.js'; +import hljsPuppet from 'highlight.js/lib/languages/puppet.js'; +import hljsPython from 'highlight.js/lib/languages/python.js'; +import hljsR from 'highlight.js/lib/languages/r.js'; +import hljsRuby from 'highlight.js/lib/languages/ruby.js'; +import hljsRust from 'highlight.js/lib/languages/rust.js'; +import hljsScala from 'highlight.js/lib/languages/scala.js'; +import hljsScheme from 'highlight.js/lib/languages/scheme.js'; +import hljsScss from 'highlight.js/lib/languages/scss.js'; +import hljsSmalltalk from 'highlight.js/lib/languages/smalltalk.js'; +import hljsSql from 'highlight.js/lib/languages/sql.js'; +import hljsSwift from 'highlight.js/lib/languages/swift.js'; +import hljsTex from 'highlight.js/lib/languages/tex.js'; +import hljsVbnet from 'highlight.js/lib/languages/vbnet.js'; +import hljsVbscript from 'highlight.js/lib/languages/vbscript.js'; +import hljsVerilog from 'highlight.js/lib/languages/verilog.js'; +import hljsXml from 'highlight.js/lib/languages/xml.js'; +import hljsYaml from 'highlight.js/lib/languages/yaml.js'; + +hlJS.registerLanguage('actionscript', hljsActionscript); +hlJS.registerLanguage('applescript', hljsApplescript); +hlJS.registerLanguage('bash', hljsBash); +hlJS.registerLanguage('clojure', hljsClojure); +hlJS.registerLanguage('coffeescript', hljsCoffeescript); +hlJS.registerLanguage('cpp', hljsCpp); +hlJS.registerLanguage('cs', hljsCs); +hlJS.registerLanguage('css', hljsCss); +hlJS.registerLanguage('d', hljsD); +hlJS.registerLanguage('dart', hljsDart); +hlJS.registerLanguage('delphi', hljsDelphi); +hlJS.registerLanguage('diff', hljsDiff); +hlJS.registerLanguage('django', hljsDjango); +hlJS.registerLanguage('dockerfile', hljsDockerfile); +hlJS.registerLanguage('erlang', hljsErlang); +hlJS.registerLanguage('fortran', hljsFortran); +hlJS.registerLanguage('fsharp', hljsFsharp); +hlJS.registerLanguage('gcode', hljsGcode); +hlJS.registerLanguage('go', hljsGo); +hlJS.registerLanguage('groovy', hljsGroovy); +hlJS.registerLanguage('handlebars', hljsHandlebars); +hlJS.registerLanguage('haskell', hljsHaskell); +hlJS.registerLanguage('haxe', hljsHaxe); +hlJS.registerLanguage('java', hljsJava); +hlJS.registerLanguage('javascript', hljsJavascript); +hlJS.registerLanguage('json', hljsJson); +hlJS.registerLanguage('julia', hljsJulia); +hlJS.registerLanguage('kotlin', hljsKotlin); +hlJS.registerLanguage('less', hljsLess); +hlJS.registerLanguage('lisp', hljsLisp); +hlJS.registerLanguage('lua', hljsLua); +hlJS.registerLanguage('makefile', hljsMakefile); +hlJS.registerLanguage('markdown', hljsMarkdown); +hlJS.registerLanguage('matlab', hljsMatlab); +hlJS.registerLanguage('objectivec', hljsObjectivec); +hlJS.registerLanguage('ocaml', hljsOcaml); +hlJS.registerLanguage('perl', hljsPerl); +hlJS.registerLanguage('php', hljsPhp); +hlJS.registerLanguage('powershell', hljsPowershell); +hlJS.registerLanguage('puppet', hljsPuppet); +hlJS.registerLanguage('python', hljsPython); +hlJS.registerLanguage('r', hljsR); +hlJS.registerLanguage('ruby', hljsRuby); +hlJS.registerLanguage('rust', hljsRust); +hlJS.registerLanguage('scala', hljsScala); +hlJS.registerLanguage('scheme', hljsScheme); +hlJS.registerLanguage('scss', hljsScss); +hlJS.registerLanguage('smalltalk', hljsSmalltalk); +hlJS.registerLanguage('sql', hljsSql); +hlJS.registerLanguage('swift', hljsSwift); +hlJS.registerLanguage('tex', hljsTex); +hlJS.registerLanguage('vbnet', hljsVbnet); +hlJS.registerLanguage('vbscript', hljsVbscript); +hlJS.registerLanguage('verilog', hljsVerilog); +hlJS.registerLanguage('xml', hljsXml); +hlJS.registerLanguage('yaml', hljsYaml); + +const HighlightedLanguages = Constants.HighlightedLanguages; + +export function formatCode(lang, data, filename) { + var language = lang || ''; + var parsed; + var header = ''; + + language = language.toLowerCase(); + + if (HighlightedLanguages[language]) { + var name = HighlightedLanguages[language].name; + + if (filename) { + const fname = decodeURIComponent(Utils.getFileName(filename)); + name = fname + ' - ' + name; + } + + header = '' + name + ''; + + try { + parsed = hlJS.highlight(language, data).value; + } catch (e) { + parsed = TextFormatting.sanitizeHtml(data); + } + } else { + parsed = TextFormatting.sanitizeHtml(data); + } + + const lines = data.match(/\r\n|\r|\n|$/g).length; + var strlines = ''; + for (var i = 1; i <= lines; i++) { + if (strlines) { + strlines += '\n' + i; + } else { + strlines += i; + } + } + + return ( + '
' + + header + + '
' +
+                '' +
+                    '' +
+                        '' +
+                            '' +
+                                '' +
+                                '' +
+                            '' +
+                        '' +
+                    '
' + strlines + '' + + parsed + + '
' + + '
' + + '
' + + '
' + ); +} + +export function getLang(filename) { + const fileInfo = Utils.splitFileLocation(filename); + var ext = fileInfo.ext; + if (!ext) { + return null; + } + + ext = ext.toLowerCase(); + for (var key in HighlightedLanguages) { + if (HighlightedLanguages[key].extensions.find((x) => x === ext)) { + return key; + } + } + return null; +} diff --git a/webapp/utils/utils.jsx b/webapp/utils/utils.jsx index fbed9a082..12a7ff50e 100644 --- a/webapp/utils/utils.jsx +++ b/webapp/utils/utils.jsx @@ -680,7 +680,7 @@ export function applyTheme(theme) { } if (theme.centerChannelBg) { - changeCss('.app__content, .markdown__table, .markdown__table tbody tr, .suggestion-list__content, .modal .modal-content', 'background:' + theme.centerChannelBg, 1); + changeCss('.app__content, .markdown__table, .markdown__table tbody tr, .suggestion-list__content, .modal .modal-content, .modal .modal-back', 'background:' + theme.centerChannelBg, 1); changeCss('#post-list .post-list-holder-by-time', 'background:' + theme.centerChannelBg, 1); changeCss('#post-create', 'background:' + theme.centerChannelBg, 1); changeCss('.date-separator .separator__text, .new-separator .separator__text', 'background:' + theme.centerChannelBg, 1); -- cgit v1.2.3-1-g7c22