2 Commits

Author SHA1 Message Date
  Dylan Baker 76a0674429 0.3.0 3 years ago
  Dylan Baker 432ef2d77e Add highlighting to code blocks 3 years ago
4 changed files with 38 additions and 12 deletions
  1. 6
    1
      package-lock.json
  2. 2
    1
      package.json
  3. 15
    3
      src/index.ts
  4. 15
    7
      src/template.ts

+ 6
- 1
package-lock.json View File

1
 {
1
 {
2
   "name": "markarth",
2
   "name": "markarth",
3
-  "version": "0.2.0",
3
+  "version": "0.3.0",
4
   "lockfileVersion": 1,
4
   "lockfileVersion": 1,
5
   "requires": true,
5
   "requires": true,
6
   "dependencies": {
6
   "dependencies": {
332
         "is-glob": "^4.0.1"
332
         "is-glob": "^4.0.1"
333
       }
333
       }
334
     },
334
     },
335
+    "highlight.js": {
336
+      "version": "10.5.0",
337
+      "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.5.0.tgz",
338
+      "integrity": "sha512-xTmvd9HiIHR6L53TMC7TKolEj65zG1XU+Onr8oi86mYa+nLcIbxTTWkpW7CsEwv/vK7u1zb8alZIMLDqqN6KTw=="
339
+    },
335
     "http-errors": {
340
     "http-errors": {
336
       "version": "1.7.2",
341
       "version": "1.7.2",
337
       "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
342
       "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",

+ 2
- 1
package.json View File

1
 {
1
 {
2
   "name": "markarth",
2
   "name": "markarth",
3
-  "version": "0.2.0",
3
+  "version": "0.3.0",
4
   "description": "Live preview local Markdown files in the browser",
4
   "description": "Live preview local Markdown files in the browser",
5
   "main": "dist/index.js",
5
   "main": "dist/index.js",
6
   "repository": {
6
   "repository": {
22
     "argparse": "^2.0.1",
22
     "argparse": "^2.0.1",
23
     "chokidar": "^3.5.1",
23
     "chokidar": "^3.5.1",
24
     "express": "^4.17.1",
24
     "express": "^4.17.1",
25
+    "highlight.js": "^10.5.0",
25
     "marked": "^1.2.8",
26
     "marked": "^1.2.8",
26
     "ws": "^7.4.2"
27
     "ws": "^7.4.2"
27
   },
28
   },

+ 15
- 3
src/index.ts View File

5
 import express, { Request, Response } from 'express';
5
 import express, { Request, Response } from 'express';
6
 import marked from 'marked';
6
 import marked from 'marked';
7
 import WebSocket from 'ws';
7
 import WebSocket from 'ws';
8
+import hljs from 'highlight.js';
8
 
9
 
9
 import * as fs from 'fs';
10
 import * as fs from 'fs';
10
 import * as path from 'path';
11
 import * as path from 'path';
22
   help: 'The port to run on',
23
   help: 'The port to run on',
23
   type: 'int',
24
   type: 'int',
24
 });
25
 });
26
+parser.add_argument('-t', '--theme', {
27
+  default: 'zenburn',
28
+  help:
29
+    'The theme to use for highlighted code blocks. A full list of available themes can be found at https://highlightjs.org/static/demo.',
30
+  type: 'str',
31
+});
25
 
32
 
26
-const { file, port } = parser.parse_args();
33
+const { file, port, theme } = parser.parse_args();
27
 const filepath = path.resolve(file);
34
 const filepath = path.resolve(file);
28
 
35
 
29
 const getRenderedHTML = () => {
36
 const getRenderedHTML = () => {
30
   const fileContents = fs.readFileSync(filepath, 'utf-8');
37
   const fileContents = fs.readFileSync(filepath, 'utf-8');
31
-  return marked(fileContents);
38
+  return marked(fileContents, {
39
+    highlight: (code, language) => {
40
+      const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
41
+      return hljs.highlight(validLanguage, code).value;
42
+    },
43
+  });
32
 };
44
 };
33
 
45
 
34
 const wss = new WebSocket.Server({
46
 const wss = new WebSocket.Server({
46
 const app = express();
58
 const app = express();
47
 
59
 
48
 app.get('/', (_req: Request, res: Response) => {
60
 app.get('/', (_req: Request, res: Response) => {
49
-  res.send(template(path.basename(file), getRenderedHTML()));
61
+  res.send(template(path.basename(file), getRenderedHTML(), theme));
50
 });
62
 });
51
 
63
 
52
 app.listen(port, () => {
64
 app.listen(port, () => {

+ 15
- 7
src/template.ts View File

3
 
3
 
4
 const defaultStylesheet = `
4
 const defaultStylesheet = `
5
   * {
5
   * {
6
+    box-sizing: border-box;
6
     margin-top: 0;
7
     margin-top: 0;
7
   }
8
   }
8
 
9
 
37
   }
38
   }
38
 
39
 
39
   pre, code {
40
   pre, code {
40
-    background: #dddddd;
41
     border-radius: 4px;
41
     border-radius: 4px;
42
     font-family: Source Code Pro;
42
     font-family: Source Code Pro;
43
     font-size: 16px;
43
     font-size: 16px;
44
     overflow-x: scroll;
44
     overflow-x: scroll;
45
   }
45
   }
46
 
46
 
47
-  pre {
48
-    padding: 5px;
49
-  }
50
-
51
   p code  {
47
   p code  {
52
     white-space: nowrap;
48
     white-space: nowrap;
53
   }
49
   }
102
   }
98
   }
103
 `;
99
 `;
104
 
100
 
105
-export default (title: string, content: string, stylesheet: string = defaultStylesheet) => `
101
+export default (
102
+  title: string,
103
+  content: string,
104
+  theme: string,
105
+  stylesheet: string = defaultStylesheet,
106
+) => `
106
   <html>
107
   <html>
107
     <head>
108
     <head>
108
       <title>Markarth - ${title}</title>
109
       <title>Markarth - ${title}</title>
109
       <meta name="viewport" content="width=device-width">
110
       <meta name="viewport" content="width=device-width">
110
       <link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css">
111
       <link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css">
112
+      <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/styles/${theme}.min.css">
111
       <style>
113
       <style>
112
         ${stylesheet}
114
         ${stylesheet}
113
       </style>
115
       </style>
122
       <script>
124
       <script>
123
         window.onload = () => {
125
         window.onload = () => {
124
           const ws = new WebSocket('ws://localhost:40510');
126
           const ws = new WebSocket('ws://localhost:40510');
127
+
125
           ws.onmessage = ({ data }) => {
128
           ws.onmessage = ({ data }) => {
126
             console.log('Changes detected, reloading');
129
             console.log('Changes detected, reloading');
127
             document.querySelector('#container').innerHTML = data;
130
             document.querySelector('#container').innerHTML = data;
128
           }
131
           }
132
+
129
           document.querySelector('#sun').addEventListener('click', (e) => {
133
           document.querySelector('#sun').addEventListener('click', (e) => {
130
             document.body.classList.toggle('dark');
134
             document.body.classList.toggle('dark');
131
           });
135
           });
136
+
132
           document.querySelector('#letter').addEventListener('click', (e) => {
137
           document.querySelector('#letter').addEventListener('click', (e) => {
133
             document.body.classList.toggle('serif');
138
             document.body.classList.toggle('serif');
134
           });
139
           });
140
+
141
+          document.querySelectorAll('pre code').forEach(codeBlock => {
142
+            codeBlock.classList.add('hljs');
143
+          });
135
         }
144
         }
136
       </script>
145
       </script>
137
     </body>
146
     </body>
138
   </html>
147
   </html>
139
 `;
148
 `;
140
-

Loading…
Cancel
Save