├── math-slack.gif ├── NEWS.md ├── LICENSE ├── README.md ├── math-with-slack.sh └── math-with-slack.bat /math-slack.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsavje/math-with-slack/HEAD/math-slack.gif -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # math-with-slack 0.2.5 2 | 3 | * Fixes bug in Windows script. 4 | 5 | 6 | # math-with-slack 0.2.4 7 | 8 | * Minor fixes. 9 | * Uses MathJax v2.7.4. 10 | 11 | 12 | # math-with-slack 0.2.3 13 | 14 | * Minor fixes. 15 | * Uses MathJax v2.7.2. 16 | 17 | 18 | # math-with-slack 0.2.2 19 | 20 | * Minor fixes. 21 | 22 | 23 | # math-with-slack 0.2.1 24 | 25 | * Minor fixes. 26 | 27 | 28 | # math-with-slack 0.2 29 | 30 | * Loads without delay. 31 | * Works when changing teams. 32 | * Uses MathJax v2.7.1. 33 | 34 | 35 | # math-with-slack 0.1 36 | 37 | * Initial release. 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-2018 Fredrik Sävje 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | :warning: :warning: This repo is not currently maintained, and the script will not work with Slack 4 or later versions. [Please refer to this fork for a version that sees active development.](https://github.com/thisiscam/math-with-slack) :warning: :warning: 2 | 3 | # Rendered math (MathJax) with Slack's desktop client 4 | 5 | [Slack](https://slack.com) does not display rendered math. The `math-with-slack` script allows you to write nice-looking math using familiar TeX syntax by injecting [MathJax](https://www.mathjax.org) into Slack's desktop client. This approach has several advantages over the plugin/bot solution: 6 | 7 | * You can write both inline- and display-style equations. 8 | * You can edit equations after you've posted them. 9 | * Nothing is sent to external servers for rendering. 10 | 11 | The downside is that equations are not rendered for team members without the MathJax injection. 12 | 13 | 14 | ![Math Slack Example](math-slack.gif "Amazing maths!") 15 | 16 | 17 | ## How do I install it? 18 | 19 | Download and run your platform's script. Restart the Slack client. You're done! 20 | 21 | 22 | ### Mac and Linux 23 | 24 | Run the following in a terminal: 25 | 26 | ```shell 27 | curl -OL https://github.com/fsavje/math-with-slack/releases/download/v0.2.5/math-with-slack.sh 28 | sudo bash math-with-slack.sh 29 | ``` 30 | 31 | 32 | ### Windows 33 | 34 | [Download the script](https://github.com/fsavje/math-with-slack/releases/download/v0.2.5/math-with-slack.bat) and double-click to run. Alternatively, run it in the command prompt with: 35 | 36 | ```shell 37 | math-with-slack.bat 38 | ``` 39 | 40 | (Windows will probably give you a security warning since the script is downloaded from Internet.) 41 | 42 | 43 | ### Package and software managers 44 | 45 | The script needs write permissions in the Slack directory in order to inject the MathJax code. Some package and software managers write protect their directories, and `math-with-slack` cannot be installed if Slack is installed through such a manager. This is the case for both the Windows Store and Snap versions of Slack. You should use the version downloaded from [Slack's website](https://slack.com/downloads/windows) if you want to use `math-with-slack`. The script should, however, work with most package managers if [you manage to grant the script write permission](https://github.com/fsavje/math-with-slack/issues/32#issuecomment-479852799). 46 | 47 | 48 | ### Uninstall 49 | 50 | To uninstall, run the script again with the `-u` flag: 51 | 52 | ```shell 53 | sudo bash math-with-slack.sh -u 54 | ``` 55 | 56 | ```shell 57 | math-with-slack.bat -u 58 | ``` 59 | 60 | 61 | ### Updating Slack 62 | 63 | The code injected by the script might be overwritten when you update the Slack app. If your client stops rendering math after an update, re-run the script as above and it should work again. 64 | 65 | 66 | ### If Slack cannot be found 67 | 68 | If you've installed Slack in some exotic place, the script might not find the installation by itself or it might find the wrong installation. In such cases, you need to specify the location of Slack's `app.asar.unpacked/src/static` folder as a parameter: 69 | 70 | ```shell 71 | sudo bash math-with-slack.sh /My_Apps/Slack.app/Contents/Resources/app.asar.unpacked/src/static 72 | ``` 73 | 74 | ```shell 75 | math-with-slack.bat E:\My_Apps\slack\app-2.5.1\resources\app.asar.unpacked\src\static 76 | ``` 77 | 78 | 79 | ## How do I get my math rendered? 80 | 81 | As you do in TeX, use `$ ... $` for inline math and `$$ ... $$` for display-style math. If you need to write a lot of dollar-signs in a message and want to prevent rendering, use backslash to escape them: `\$`. 82 | 83 | Note that only users with MathJax injected in their client will see the rendered version of your math. Users with the standard client will see the equations just as you wrote them (i.e., unrendered including the dollar signs). 84 | 85 | 86 | ## How does it work? 87 | 88 | The script alters how Slack is loaded. Under the hood, the desktop client is based on ordinary web technology. The modified client loads the [MathJax library](https://www.mathjax.org) after start-up and adds a listener for messages. As soon as it detects a new message, it looks for TeX-styled math and tries to render. Everything is done in the client. Messages are *never* sent to servers for rendering. 89 | 90 | 91 | ## Can I contribute? 92 | 93 | Yes, please. Just add an [issue](https://github.com/fsavje/math-with-slack/issues) or a [pull request](https://github.com/fsavje/math-with-slack/pulls). 94 | 95 | 96 | **Thanks to past contributors:** 97 | 98 | * [Caster](https://github.com/Caster) 99 | * [chrispanag](https://github.com/chrispanag) 100 | * [crstnbr](https://github.com/crstnbr) 101 | * [gauss256](https://github.com/gauss256) 102 | * [jeanluct](https://github.com/jeanluct) 103 | * [LaurentHayez](https://github.com/LaurentHayez) 104 | * [NKudryavka](https://github.com/NKudryavka) 105 | * [peroxyacyl](https://github.com/peroxyacyl) 106 | * [Spenhouet](https://github.com/Spenhouet) 107 | * [Xyene](https://github.com/Xyene) 108 | 109 | 110 | **Inspiration** 111 | 112 | This [comment](https://gist.github.com/DrewML/0acd2e389492e7d9d6be63386d75dd99#gistcomment-1981178) by [jouni](https://github.com/jouni) was extremely helpful. So was this [snippet](https://gist.github.com/etihwnad/bc63ec9b87af586e1435) by [etihwnad](https://github.com/etihwnad). 113 | -------------------------------------------------------------------------------- /math-with-slack.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ################################################################################ 4 | # Rendered math (MathJax) with Slack's desktop client 5 | ################################################################################ 6 | # 7 | # Slack (https://slack.com) does not display rendered math. This script 8 | # injects MathJax (https://www.mathjax.org) into Slack's desktop client, 9 | # which allows you to write nice-looking inline- and display-style math 10 | # using familiar TeX/LaTeX syntax. 11 | # 12 | # https://github.com/fsavje/math-with-slack 13 | # 14 | # MIT License, Copyright 2017-2018 Fredrik Savje 15 | # 16 | ################################################################################ 17 | 18 | 19 | ## Constants 20 | 21 | MWS_VERSION="v0.2.5" 22 | 23 | 24 | ## Functions 25 | 26 | error() { 27 | echo "$(tput setaf 124)$(tput bold)✘ $1$(tput sgr0)" 28 | exit 1 29 | } 30 | 31 | 32 | ## User input 33 | 34 | for p in "$@"; do 35 | if [ "$p" = "-u" ]; then 36 | UNINSTALL="$p" 37 | else 38 | SLACK_DIR="$p" 39 | fi 40 | done 41 | 42 | 43 | ## Platform settings 44 | 45 | if [ "$(uname)" == "Darwin" ]; then 46 | # macOS 47 | COMMON_SLACK_LOCATIONS=( 48 | "/Applications/Slack.app/Contents/Resources/app.asar.unpacked/src/static" 49 | ) 50 | else 51 | # Linux 52 | COMMON_SLACK_LOCATIONS=( 53 | "/usr/lib/slack/resources/app.asar.unpacked/src/static" 54 | "/usr/local/lib/slack/resources/app.asar.unpacked/src/static" 55 | "/opt/slack/resources/app.asar.unpacked/src/static" 56 | ) 57 | fi 58 | 59 | 60 | ## Try to find slack if not provided by user 61 | 62 | if [ -z "$SLACK_DIR" ]; then 63 | for loc in "${COMMON_SLACK_LOCATIONS[@]}"; do 64 | if [ -e "$loc" ]; then 65 | SLACK_DIR="$loc" 66 | break 67 | fi 68 | done 69 | fi 70 | 71 | 72 | ## Files 73 | 74 | SLACK_MATHJAX_SCRIPT="$SLACK_DIR/math-with-slack.js" 75 | SLACK_SSB_INTEROP="$SLACK_DIR/ssb-interop.js" 76 | 77 | 78 | ## Check so installation exists and is writable 79 | 80 | if [ -z "$SLACK_DIR" ]; then 81 | error "Cannot find Slack installation." 82 | elif [ ! -e "$SLACK_DIR" ]; then 83 | error "Cannot find Slack installation at: $SLACK_DIR" 84 | elif [ ! -e "$SLACK_SSB_INTEROP" ]; then 85 | error "Cannot find Slack file: $SLACK_SSB_INTEROP" 86 | elif [ ! -w "$SLACK_SSB_INTEROP" ]; then 87 | error "Cannot write to Slack file: $SLACK_SSB_INTEROP" 88 | fi 89 | 90 | echo "Using Slack installation at: $SLACK_DIR" 91 | 92 | 93 | ## Remove previous version 94 | 95 | if [ -e "$SLACK_MATHJAX_SCRIPT" ]; then 96 | rm $SLACK_MATHJAX_SCRIPT 97 | fi 98 | 99 | 100 | ## Restore previous injections 101 | 102 | # Check whether file been injected. If not, assume it's more recent than backup 103 | if grep -q "math-with-slack" $SLACK_SSB_INTEROP; then 104 | if [ -e "$SLACK_SSB_INTEROP.mwsbak" ]; then 105 | mv -f $SLACK_SSB_INTEROP.mwsbak $SLACK_SSB_INTEROP 106 | else 107 | error "Cannot restore from backup. Missing file: $SLACK_SSB_INTEROP.mwsbak" 108 | fi 109 | elif [ -e "$SLACK_SSB_INTEROP.mwsbak" ]; then 110 | rm $SLACK_SSB_INTEROP.mwsbak 111 | fi 112 | 113 | 114 | ## Are we uninstalling? 115 | 116 | if [ -n "$UNINSTALL" ]; then 117 | echo "$(tput setaf 64)math-with-slack has been uninstalled. Please restart the Slack client.$(tput sgr0)" 118 | exit 0 119 | fi 120 | 121 | 122 | ## Write main script 123 | 124 | cat < $SLACK_MATHJAX_SCRIPT 125 | // math-with-slack $MWS_VERSION 126 | // https://github.com/fsavje/math-with-slack 127 | 128 | document.addEventListener('DOMContentLoaded', function() { 129 | var mathjax_config = document.createElement('script'); 130 | mathjax_config.type = 'text/x-mathjax-config'; 131 | mathjax_config.text = \` 132 | MathJax.Hub.Config({ 133 | messageStyle: 'none', 134 | extensions: ['tex2jax.js'], 135 | jax: ['input/TeX', 'output/HTML-CSS'], 136 | tex2jax: { 137 | displayMath: [['\$\$', '\$\$']], 138 | element: 'msgs_div', 139 | ignoreClass: 'ql-editor', 140 | inlineMath: [['\$', '\$']], 141 | processEscapes: true, 142 | skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code'] 143 | }, 144 | TeX: { 145 | extensions: ['AMSmath.js', 'AMSsymbols.js', 'noErrors.js', 'noUndefined.js'] 146 | } 147 | }); 148 | \`; 149 | 150 | var mathjax_observer = document.createElement('script'); 151 | mathjax_observer.type = 'text/x-mathjax-config'; 152 | mathjax_observer.text = \` 153 | var target = document.querySelector('#messages_container'); 154 | var options = { attributes: false, childList: true, characterData: true, subtree: true }; 155 | var observer = new MutationObserver(function (r, o) { MathJax.Hub.Queue(['Typeset', MathJax.Hub]); }); 156 | observer.observe(target, options); 157 | \`; 158 | 159 | var mathjax_script = document.createElement('script'); 160 | mathjax_script.type = 'text/javascript'; 161 | mathjax_script.src = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.4/MathJax.js'; 162 | 163 | document.head.appendChild(mathjax_config); 164 | document.head.appendChild(mathjax_observer); 165 | document.head.appendChild(mathjax_script); 166 | }); 167 | EOF 168 | 169 | 170 | ## Inject code loader 171 | 172 | # Check so not already injected 173 | if grep -q "math-with-slack" $SLACK_SSB_INTEROP; then 174 | error "File already injected: $SLACK_SSB_INTEROP" 175 | fi 176 | 177 | # Make backup 178 | if [ ! -e "$SLACK_SSB_INTEROP.mwsbak" ]; then 179 | cp $SLACK_SSB_INTEROP $SLACK_SSB_INTEROP.mwsbak 180 | else 181 | error "Backup already exists: $SLACK_SSB_INTEROP.mwsbak" 182 | fi 183 | 184 | # Inject loader code 185 | ed -s $SLACK_SSB_INTEROP < /dev/null 186 | /init(resourcePath, mainModule, !isDevMode); 187 | i 188 | // ** math-with-slack $MWS_VERSION ** https://github.com/fsavje/math-with-slack 189 | var mwsp = path.join(__dirname, 'math-with-slack.js').replace('app.asar', 'app.asar.unpacked'); 190 | require('fs').readFile(mwsp, 'utf8', (e, r) => { if (e) { throw e; } else { eval(r); } }); 191 | 192 | . 193 | w 194 | q 195 | EOF 196 | 197 | 198 | ## We're done 199 | 200 | echo "$(tput setaf 64)math-with-slack has been installed. Please restart the Slack client.$(tput sgr0)" 201 | -------------------------------------------------------------------------------- /math-with-slack.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 4 | :: Rendered math (MathJax) with Slack's desktop client 5 | :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 6 | :: 7 | :: Slack (https://slack.com) does not display rendered math. This script 8 | :: injects MathJax (https://www.mathjax.org) into Slack's desktop client, 9 | :: which allows you to write nice-looking inline- and display-style math 10 | :: using familiar TeX/LaTeX syntax. 11 | :: 12 | :: https://github.com/fsavje/math-with-slack 13 | :: 14 | :: MIT License, Copyright 2017-2018 Fredrik Savje 15 | :: 16 | :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 17 | 18 | 19 | :: Constants 20 | 21 | SET "MWS_VERSION=v0.2.5" 22 | 23 | 24 | :: User input 25 | 26 | SET "UNINSTALL=" 27 | SET "SLACK_DIR=" 28 | 29 | :parse 30 | IF "%~1" == "" GOTO endparse 31 | IF "%~1" == "-u" ( 32 | SET UNINSTALL=%~1 33 | ) ELSE ( 34 | SET SLACK_DIR=%~1 35 | ) 36 | SHIFT 37 | GOTO parse 38 | :endparse 39 | 40 | 41 | :: Try to find slack if not provided by user 42 | 43 | IF "%SLACK_DIR%" == "" ( 44 | FOR /F %%t IN ('DIR /B /OD "%UserProfile%\AppData\Local\slack\app-?.*.*"') DO ( 45 | SET "SLACK_DIR=%UserProfile%\AppData\Local\slack\%%t\resources\app.asar.unpacked\src\static" 46 | ) 47 | ) 48 | 49 | 50 | :: Files 51 | 52 | SET "SLACK_MATHJAX_SCRIPT=%SLACK_DIR%\math-with-slack.js" 53 | SET "SLACK_SSB_INTEROP=%SLACK_DIR%\ssb-interop.js" 54 | 55 | 56 | :: Check so installation exists 57 | 58 | IF "%SLACK_DIR%" == "" ( 59 | ECHO Cannot find Slack installation. 60 | PAUSE & EXIT /B 1 61 | ) 62 | 63 | IF NOT EXIST "%SLACK_DIR%" ( 64 | ECHO Cannot find Slack installation at: %SLACK_DIR% 65 | PAUSE & EXIT /B 1 66 | ) 67 | 68 | IF NOT EXIST "%SLACK_SSB_INTEROP%" ( 69 | ECHO Cannot find Slack file: %SLACK_SSB_INTEROP% 70 | PAUSE & EXIT /B 1 71 | ) 72 | 73 | 74 | ECHO Using Slack installation at: %SLACK_DIR% 75 | 76 | 77 | :: Remove previous version 78 | 79 | IF EXIST "%SLACK_MATHJAX_SCRIPT%" ( 80 | DEL "%SLACK_MATHJAX_SCRIPT%" 81 | ) 82 | 83 | 84 | :: Restore previous injections 85 | 86 | FINDSTR /R /C:"math-with-slack" "%SLACK_SSB_INTEROP%" >NUL 87 | IF %ERRORLEVEL% EQU 0 ( 88 | IF EXIST "%SLACK_SSB_INTEROP%.mwsbak" ( 89 | MOVE /Y "%SLACK_SSB_INTEROP%.mwsbak" "%SLACK_SSB_INTEROP%" >NUL 90 | ) ELSE ( 91 | ECHO Cannot restore from backup. Missing file: %SLACK_SSB_INTEROP%.mwsbak 92 | PAUSE & EXIT /B 1 93 | ) 94 | ) ELSE ( 95 | IF EXIST "%SLACK_SSB_INTEROP%.mwsbak" ( 96 | DEL "%SLACK_SSB_INTEROP%.mwsbak" 97 | ) 98 | ) 99 | 100 | 101 | :: Are we uninstalling? 102 | 103 | IF "%UNINSTALL%" == "-u" ( 104 | ECHO math-with-slack has been uninstalled. Please restart the Slack client. 105 | PAUSE & EXIT /B 0 106 | ) 107 | 108 | 109 | :: Write main script 110 | 111 | >"%SLACK_MATHJAX_SCRIPT%" ( 112 | ECHO.// math-with-slack %MWS_VERSION% 113 | ECHO.// https://github.com/fsavje/math-with-slack 114 | ECHO. 115 | ECHO.document.addEventListener('DOMContentLoaded', function(^) { 116 | ECHO. var mathjax_config = document.createElement('script'^); 117 | ECHO. mathjax_config.type = 'text/x-mathjax-config'; 118 | ECHO. mathjax_config.text = ` 119 | ECHO. MathJax.Hub.Config({ 120 | ECHO. messageStyle: 'none', 121 | ECHO. extensions: ['tex2jax.js'], 122 | ECHO. jax: ['input/TeX', 'output/HTML-CSS'], 123 | ECHO. tex2jax: { 124 | ECHO. displayMath: [['\$\$', '\$\$']], 125 | ECHO. element: 'msgs_div', 126 | ECHO. ignoreClass: 'ql-editor', 127 | ECHO. inlineMath: [['\$', '\$']], 128 | ECHO. processEscapes: true, 129 | ECHO. skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code'] 130 | ECHO. }, 131 | ECHO. TeX: { 132 | ECHO. extensions: ['AMSmath.js', 'AMSsymbols.js', 'noErrors.js', 'noUndefined.js'] 133 | ECHO. } 134 | ECHO. }^); 135 | ECHO. `; 136 | ECHO. 137 | ECHO. var mathjax_observer = document.createElement('script'^); 138 | ECHO. mathjax_observer.type = 'text/x-mathjax-config'; 139 | ECHO. mathjax_observer.text = ` 140 | ECHO. var target = document.querySelector('#messages_container'^); 141 | ECHO. var options = { attributes: false, childList: true, characterData: true, subtree: true }; 142 | ECHO. var observer = new MutationObserver(function (r, o^) { MathJax.Hub.Queue(['Typeset', MathJax.Hub]^); }^); 143 | ECHO. observer.observe(target, options^); 144 | ECHO. `; 145 | ECHO. 146 | ECHO. var mathjax_script = document.createElement('script'^); 147 | ECHO. mathjax_script.type = 'text/javascript'; 148 | ECHO. mathjax_script.src = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.4/MathJax.js'; 149 | ECHO. 150 | ECHO. document.head.appendChild(mathjax_config^); 151 | ECHO. document.head.appendChild(mathjax_observer^); 152 | ECHO. document.head.appendChild(mathjax_script^); 153 | ECHO.}^); 154 | ) 155 | 156 | 157 | :: Check so not already injected 158 | 159 | FINDSTR /R /C:"math-with-slack" "%SLACK_SSB_INTEROP%" >NUL 160 | IF %ERRORLEVEL% EQU 0 ( 161 | ECHO File already injected: %SLACK_SSB_INTEROP% 162 | PAUSE & EXIT /B 1 163 | ) 164 | 165 | 166 | :: Make backup 167 | 168 | IF NOT EXIST "%SLACK_SSB_INTEROP%.mwsbak" ( 169 | MOVE /Y "%SLACK_SSB_INTEROP%" "%SLACK_SSB_INTEROP%.mwsbak" >NUL 170 | ) ELSE ( 171 | ECHO Backup already exists: %SLACK_SSB_INTEROP%.mwsbak 172 | PAUSE & EXIT /B 1 173 | ) 174 | 175 | 176 | :: Inject loader code 177 | 178 | FOR /F "delims=" %%L IN (%SLACK_SSB_INTEROP%.mwsbak) DO ( 179 | IF "%%L" == " init(resourcePath, mainModule, !isDevMode);" ( 180 | >>"%SLACK_SSB_INTEROP%" ( 181 | ECHO. // ** math-with-slack %MWS_VERSION% ** https://github.com/fsavje/math-with-slack 182 | ECHO. var mwsp = path.join(__dirname, 'math-with-slack.js'^).replace('app.asar', 'app.asar.unpacked'^); 183 | ECHO. require('fs'^).readFile(mwsp, 'utf8', (e, r^) =^> { if (e^) { throw e; } else { eval(r^); } }^); 184 | ECHO. 185 | ECHO. init(resourcePath, mainModule, !isDevMode^); 186 | ) 187 | ) ELSE ( 188 | >>"%SLACK_SSB_INTEROP%" ECHO.%%L 189 | ) 190 | ) 191 | 192 | 193 | :: We're done 194 | 195 | ECHO math-with-slack has been installed. Please restart the Slack client. 196 | PAUSE & EXIT /B 0 197 | --------------------------------------------------------------------------------