Browse Source

Initial commit

tags/v0.2.0
Dylan Baker 2 years ago
commit
22624cebbd
10 changed files with 2402 additions and 0 deletions
  1. 2
    0
      .gitignore
  2. 19
    0
      LICENSE
  3. 21
    0
      README.md
  4. 2100
    0
      package-lock.json
  5. 36
    0
      package.json
  6. 7
    0
      src/assets/letter.ts
  7. 15
    0
      src/assets/sun.ts
  8. 58
    0
      src/index.ts
  9. 126
    0
      src/template.ts
  10. 18
    0
      tsconfig.json

+ 2
- 0
.gitignore View File

@@ -0,0 +1,2 @@
1
+node_modules
2
+dist

+ 19
- 0
LICENSE View File

@@ -0,0 +1,19 @@
1
+Copyright 2019 Dylan Baker
2
+
3
+Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+this software and associated documentation files (the "Software"), to deal in
5
+the Software without restriction, including without limitation the rights to
6
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
+of the Software, and to permit persons to whom the Software is furnished to do
8
+so, subject to the following conditions:
9
+
10
+The above copyright notice and this permission notice shall be included in all
11
+copies or substantial portions of the Software.
12
+
13
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+SOFTWARE.

+ 21
- 0
README.md View File

@@ -0,0 +1,21 @@
1
+# Markarth
2
+
3
+Markarth is a tool for previewing local Markdown files live in a web browser.
4
+You can edit your document in your favorite editor and Markarth will watch that
5
+file for changes and push the changes to your browser.
6
+
7
+## Installation
8
+
9
+```
10
+$ npm install -g markarth
11
+```
12
+
13
+## Usage
14
+
15
+```
16
+$ markarth my-document.md
17
+```
18
+
19
+## License
20
+
21
+MIT

+ 2100
- 0
package-lock.json
File diff suppressed because it is too large
View File


+ 36
- 0
package.json View File

@@ -0,0 +1,36 @@
1
+{
2
+  "name": "markarth",
3
+  "version": "0.1.0",
4
+  "description": "Live preview local Markdown files in the browser",
5
+  "main": "dist/index.js",
6
+  "repository": {
7
+    "type": "git",
8
+    "url": "https://git.sr.ht/~simulacrumparty/markarth"
9
+  },
10
+  "bin": {
11
+    "markarth": "dist/index.js"
12
+  },
13
+  "scripts": {
14
+    "build": "tsc",
15
+    "prepare" : "npm run build",
16
+    "postversion" : "git push && git push --tags"
17
+  },
18
+  "keywords": [],
19
+  "author": "Dylan Baker <dylan@simulacrum.party>",
20
+  "license": "MIT",
21
+  "dependencies": {
22
+    "argparse": "^1.0.10",
23
+    "chokidar": "^2.0.4",
24
+    "express": "^4.16.4",
25
+    "remarkable": "^1.7.1",
26
+    "ws": "^6.1.2"
27
+  },
28
+  "devDependencies": {
29
+    "@types/argparse": "^1.0.35",
30
+    "@types/chokidar": "^1.7.5",
31
+    "@types/express": "^4.16.0",
32
+    "@types/remarkable": "^1.7.2",
33
+    "@types/ws": "^6.0.1",
34
+    "typescript": "^3.2.4"
35
+  }
36
+}

+ 7
- 0
src/assets/letter.ts View File

@@ -0,0 +1,7 @@
1
+export default `
2
+<?xml version="1.0" encoding="UTF-8" ?>
3
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
4
+  width="24" height="24" id="letter">
5
+  <text x="16" y="20" style="font-family:Times New Roman, 'Times New Roman', serif; font-size: 24px; text-anchor:middle;" fill="currentColor">A</text>
6
+</svg>
7
+`;

+ 15
- 0
src/assets/sun.ts View File

@@ -0,0 +1,15 @@
1
+export default `
2
+<?xml version="1.0" encoding="UTF-8" ?>
3
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
4
+  width="24" height="24" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="currentColor" id="sun">
5
+  <circle cx="12" cy="12" r="5"/>
6
+  <line x1="12" y1="1" x2="12" y2="3"/>
7
+  <line x1="12" y1="21" x2="12" y2="23"/>
8
+  <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/>
9
+  <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/>
10
+  <line x1="1" y1="12" x2="3" y2="12"/>
11
+  <line x1="21" y1="12" x2="23" y2="12"/>
12
+  <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/>
13
+  <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/>
14
+</svg>
15
+`;

+ 58
- 0
src/index.ts View File

@@ -0,0 +1,58 @@
1
+#!/usr/bin/env node
2
+
3
+import { ArgumentParser } from 'argparse';
4
+import chokidar from 'chokidar';
5
+import express, { Request, Response } from 'express';
6
+import Remarkable from 'remarkable';
7
+import WebSocket from 'ws';
8
+
9
+import * as fs from 'fs';
10
+import * as path from 'path';
11
+
12
+import template from './template';
13
+
14
+const parser = new ArgumentParser({
15
+  version: '0.1.0',
16
+  addHelp: true,
17
+  description: 'Realtime Markdown preview',
18
+});
19
+
20
+parser.addArgument('file');
21
+parser.addArgument(
22
+  ['-p', '--port'],
23
+  {
24
+    defaultValue: 1729,
25
+    help: 'The port to run on',
26
+    type: 'int' }
27
+);
28
+
29
+const { file, port } = parser.parseArgs();
30
+const filepath = path.resolve(file);
31
+
32
+const getRenderedHTML = () => {
33
+  const md = new Remarkable();
34
+  const fileContents = fs.readFileSync(filepath, 'utf-8');
35
+  return md.render(fileContents);
36
+};
37
+
38
+const wss = new WebSocket.Server({
39
+  port: 40510,
40
+});
41
+
42
+wss.on('connection', (ws) => {
43
+  chokidar.watch(filepath).on('change', () => {
44
+    ws.send(getRenderedHTML(), (err) => {
45
+      if (err) console.log(err);
46
+    });
47
+  });
48
+});
49
+
50
+const app = express();
51
+
52
+app.get('/', (_req: Request, res: Response) => {
53
+  res.send(template(path.basename(file), getRenderedHTML()));
54
+});
55
+
56
+app.listen(port, () => {
57
+  console.log(`Listening at http://localhost:${port}`);
58
+});

+ 126
- 0
src/template.ts View File

@@ -0,0 +1,126 @@
1
+import letter from './assets/letter';
2
+import sun from './assets/sun';
3
+
4
+const defaultStylesheet = `
5
+  * {
6
+    margin-top: 0;
7
+  }
8
+
9
+  body {
10
+    background: #eaeaea;
11
+    color: #121212;
12
+    font-family: Helvetica Neue, sans-serif;
13
+    font-size: 16px;
14
+    margin: 0;
15
+  }
16
+
17
+  body.dark {
18
+    background: #121212;
19
+    color: #eaeaea;
20
+  }
21
+
22
+  body.serif {
23
+    font-family: Garamond, serif;
24
+  }
25
+
26
+  a {
27
+    color: #0366d6;
28
+    text-decoration: none;
29
+  }
30
+
31
+  a:hover {
32
+    text-decoration: underline;
33
+  }
34
+
35
+  body.dark a {
36
+    color: #46a9ff;
37
+  }
38
+
39
+  pre, code {
40
+    background: #dddddd;
41
+    border-radius: 4px;
42
+    font-family: Source Code Pro;
43
+    font-size: 16px;
44
+    padding: 4px;
45
+    white-space: nowrap;
46
+  }
47
+
48
+  body.dark pre, body.dark code {
49
+    background: #333333;
50
+  }
51
+
52
+  td {
53
+    padding: .5em;
54
+  }
55
+
56
+  #settings, #container {
57
+    box-sizing: border-box;
58
+    margin: auto;
59
+    max-width: 700px;
60
+    padding: 0 1em;
61
+    width: 100%;
62
+  }
63
+
64
+  #settings {
65
+    display: flex;
66
+    padding: 1em;
67
+  }
68
+
69
+  #sun, #letter {
70
+    cursor: pointer;
71
+  }
72
+
73
+  #sun:hover, #letter:hover {
74
+    transform: scale(1.1);
75
+  }
76
+
77
+  #sun {
78
+    margin-right: 1em;
79
+  }
80
+
81
+  #container {
82
+    line-height: 1.5;
83
+  }
84
+
85
+  h2 {
86
+    border-bottom: 1px solid #dddddd;
87
+    padding-bottom: .3em;
88
+  }
89
+`;
90
+
91
+export default (title: string, content: string, stylesheet: string = defaultStylesheet) => `
92
+  <html>
93
+    <head>
94
+      <title>Markarth - ${title}</title>
95
+      <meta name="viewport" content="width=device-width">
96
+      <link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css">
97
+      <style>
98
+        ${stylesheet}
99
+      </style>
100
+    </head>
101
+    <body>
102
+      <div id="settings">
103
+        ${sun} ${letter}
104
+      </div>
105
+      <div id="container">
106
+        ${content}
107
+      </div>
108
+      <script>
109
+        window.onload = () => {
110
+          const ws = new WebSocket('ws://localhost:40510');
111
+          ws.onmessage = ({ data }) => {
112
+            console.log('Changes detected, reloading');
113
+            document.querySelector('#container').innerHTML = data;
114
+          }
115
+          document.querySelector('#sun').addEventListener('click', (e) => {
116
+            document.body.classList.toggle('dark');
117
+          });
118
+          document.querySelector('#letter').addEventListener('click', (e) => {
119
+            document.body.classList.toggle('serif');
120
+          });
121
+        }
122
+      </script>
123
+    </body>
124
+  </html>
125
+`;
126
+

+ 18
- 0
tsconfig.json View File

@@ -0,0 +1,18 @@
1
+{
2
+  "compilerOptions": {
3
+    "target": "es5",
4
+    "module": "commonjs",
5
+    "outDir": "dist",
6
+    "strict": true,
7
+    "noImplicitAny": true,
8
+    "strictNullChecks": true,
9
+    "strictFunctionTypes": true,
10
+    "noImplicitThis": true,
11
+    "alwaysStrict": true,
12
+
13
+    "noUnusedLocals": true,
14
+    "noUnusedParameters": true,
15
+    "noImplicitReturns": true,
16
+    "esModuleInterop": true
17
+  }
18
+}

Loading…
Cancel
Save