Compare commits
2 Commits
ec92cdcece
...
9616a1b514
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9616a1b514 | ||
|
|
1b867fddfe |
8
Server/MarkdownPreviewer/__init__.py
Normal file
8
Server/MarkdownPreviewer/__init__.py
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
from .server import main
|
||||||
|
import asyncio
|
||||||
|
import argparse
|
||||||
|
import sys
|
||||||
|
|
||||||
|
def launcher():
|
||||||
|
print(sys.argv)
|
||||||
|
asyncio.run(main())
|
||||||
94
Server/MarkdownPreviewer/render_pipeline.py
Normal file
94
Server/MarkdownPreviewer/render_pipeline.py
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
# Render pipeline for markdown documents.
|
||||||
|
# Allows filtering and mapping based on blocks and meta keys.
|
||||||
|
#
|
||||||
|
|
||||||
|
import pandoc
|
||||||
|
|
||||||
|
class MetaCallback:
|
||||||
|
def __init__(self, key, callback, replace=False):
|
||||||
|
self.key = key
|
||||||
|
self.callback = callback
|
||||||
|
self.replace = replace
|
||||||
|
|
||||||
|
def __call__(self, data):
|
||||||
|
return self.callback(data)
|
||||||
|
|
||||||
|
class MultiCallback:
|
||||||
|
def __init__(self, filter):
|
||||||
|
self.filter = filter
|
||||||
|
self.callbacks = dict()
|
||||||
|
|
||||||
|
def AddCallback(self, key, callback):
|
||||||
|
self.callbacks[key] = callback
|
||||||
|
|
||||||
|
def __call__(self, block):
|
||||||
|
filter_key = self.filter(block)
|
||||||
|
|
||||||
|
if filter_key is None:
|
||||||
|
return block
|
||||||
|
|
||||||
|
if filter_key in self.callbacks.keys():
|
||||||
|
return self.callbacks[filter_key](block)
|
||||||
|
else:
|
||||||
|
return block
|
||||||
|
|
||||||
|
|
||||||
|
class RenderPipeline:
|
||||||
|
def __init__(self):
|
||||||
|
self.pandoc = pandoc.Pandoc()
|
||||||
|
self.metacallbacks = dict()
|
||||||
|
self.callbacks = dict()
|
||||||
|
|
||||||
|
def AddMetaCallback(self, key, callback, replace=False):
|
||||||
|
self.metacallbacks[key] = MetaCallback(key, callback, replace)
|
||||||
|
|
||||||
|
def AddCallback(self, key, callback, replace=False):
|
||||||
|
self.callbacks[key] = {'cb' : callback, 'replace' : replace}
|
||||||
|
|
||||||
|
def ParseBlock(self, block):
|
||||||
|
|
||||||
|
if 'c' not in block:
|
||||||
|
return block
|
||||||
|
|
||||||
|
if isinstance(block['c'], dict):
|
||||||
|
content = self.ParseBlock(block['c'])
|
||||||
|
elif isinstance(block['c'], list):
|
||||||
|
content = self.ParseList(block['c'])
|
||||||
|
else:
|
||||||
|
return block
|
||||||
|
|
||||||
|
if block['t'] in self.callbacks.keys():
|
||||||
|
if self.callbacks[block['t']]['replace'] == True:
|
||||||
|
return self.callbacks[block['t']]['cb'](block)
|
||||||
|
else:
|
||||||
|
self.callbacks[block['t']]['cb'](block)
|
||||||
|
|
||||||
|
return block
|
||||||
|
|
||||||
|
def ParseList(self, pandoc_list):
|
||||||
|
output_list = list()
|
||||||
|
for item in pandoc_list:
|
||||||
|
if isinstance(item, dict):
|
||||||
|
output_list.append(self.ParseBlock(item))
|
||||||
|
else:
|
||||||
|
output_list.append(item)
|
||||||
|
|
||||||
|
return output_list
|
||||||
|
|
||||||
|
def __call__(self, data):
|
||||||
|
json_data = self.pandoc.ConvertToJson(data)
|
||||||
|
|
||||||
|
for meta_key, meta_value in json_data['meta'].items():
|
||||||
|
if meta_key in self.metacallbacks.keys():
|
||||||
|
if self.metacallbacks[meta_key].replace == True:
|
||||||
|
json_data['meta'][meta_key] = \
|
||||||
|
self.metacallbacks[meta_key](meta_value)
|
||||||
|
else:
|
||||||
|
self.metacallbacks[meta_key](meta_value)
|
||||||
|
|
||||||
|
json_data['blocks'] = self.ParseList(json_data['blocks'])
|
||||||
|
|
||||||
|
return_data = self.pandoc.ConvertFromJson(json_data)
|
||||||
|
|
||||||
|
return return_data
|
||||||
|
|
||||||
66
Server/MarkdownPreviewer/template/index.html
Normal file
66
Server/MarkdownPreviewer/template/index.html
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<link rel="stylesheet" href="highlight/styles/tokyo-night-dark.min.css">
|
||||||
|
<script src="highlight/highlight.min.js"></script>
|
||||||
|
<link href="katex/katex.min.css" rel="stylesheet" type="text/css">
|
||||||
|
<script src="katex/katex.min.js"></script>
|
||||||
|
<script src="katex/contrib/auto-render.min.js"></script>
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="page-container">
|
||||||
|
<header class="page-header">
|
||||||
|
<h1 class="page-title">Your Note Title</h1>
|
||||||
|
<div class="page-subtitle">
|
||||||
|
<div class="page-author">Author: Your Name</div>
|
||||||
|
<div class="page-date">Date: August 1, 2025</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div id="page-content" class="page-content">
|
||||||
|
{% raw body_content %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
hljs.highlightAll();
|
||||||
|
renderMathInElement(
|
||||||
|
document.body,
|
||||||
|
{
|
||||||
|
delimiters : [
|
||||||
|
{left: "$$", right: "$$", display: true},
|
||||||
|
{left: "\\[", right: "\\]", display: true},
|
||||||
|
{left: "$", right: "$", display: false},
|
||||||
|
{left: "\\(", right: "\\)", display: false}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
const socket = new WebSocket("ws://localhost:8888/ws");
|
||||||
|
|
||||||
|
socket.addEventListener("open", (event) => {
|
||||||
|
socket.send("ping");
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.addEventListener("message", (event) => {
|
||||||
|
var data = JSON.parse(event.data);
|
||||||
|
var node = document.getElementById("page-content");
|
||||||
|
var wrapper = document.createElement('div');
|
||||||
|
wrapper.innerHTML = data['show'];
|
||||||
|
node.replaceChildren(wrapper);
|
||||||
|
|
||||||
|
hljs.highlightAll();
|
||||||
|
renderMathInElement(
|
||||||
|
node,
|
||||||
|
{
|
||||||
|
delimiters : [
|
||||||
|
{left: "$$", right: "$$", display: true},
|
||||||
|
{left: "\\[", right: "\\]", display: true},
|
||||||
|
{left: "$", right: "$", display: false},
|
||||||
|
{left: "\\(", right: "\\)", display: false}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
2
Server/requirements.txt
Normal file
2
Server/requirements.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
tornado
|
||||||
|
msgpack
|
||||||
20
Server/setup.py
Normal file
20
Server/setup.py
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
|
with open('requirements.txt') as f:
|
||||||
|
requirements = f.read().splitlines()
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name="MarkdownPreviewer",
|
||||||
|
version="0.0.1",
|
||||||
|
include_pacakge_data=True,
|
||||||
|
python_requires=">=3.8",
|
||||||
|
setup_requires=['setuptools-git-versioning'],
|
||||||
|
install_requires=requirements,
|
||||||
|
author="Folkert Kevelam",
|
||||||
|
author_email="folkert@pyllr.nl",
|
||||||
|
description="A markdown previewer",
|
||||||
|
long_description="",
|
||||||
|
long_description_content_type="text/markdown",
|
||||||
|
classifiers=[],
|
||||||
|
version_config={}
|
||||||
|
)
|
||||||
Loading…
Reference in New Issue
Block a user