Skip to content
This repository was archived by the owner on Dec 14, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 78 additions & 24 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
.. image:: https://raw.githubusercontent.com/PtPrashantTripathi/markdown-server/master/markdownserver-logo.webp
:alt: "Markdown Server Logo"
:width: 300px
:align: center

===============
Markdown Server
===============

Markdown-server is a simple web application.
It converts markdown file to HTML and response by `text/html`.
It converts markdown files to HTML and responds with `text/html`.

How to use
==========
Expand All @@ -29,63 +34,112 @@ Just try
Start server
------------

You don't need any special preparation to try to start server. Just execute below commands.
You can install `markdown-server` from **PyPi** or run it directly from the repository.

### Install from PyPi:
::

(.venv)$ pip install markdown-server
(.venv)$ markdownserver --host localhost --port 8009 --debug

Bottle v0.12.8 server starting up (using WSGIRefServer())...
Listening on http://localhost:8009/

### Install from GitHub:
::

$ git clone https://github.com/ohbarye/markdown-server
$ cd markdown-server
$ virtualenv .venv
$ source .venv/bin/activate
(.venv)$ pip install -r requirements.txt
(.venv)$ markdownserver
(.venv)$ markdownserver --host localhost --port 8009 --debug
Bottle v0.12.8 server starting up (using WSGIRefServer())...
Listening on http://localhost:8009/

Or, you can install from PyPi.
If the server starts up successfully, browse the below URL and check the converted result.

::

(.venv)$ pip install markdown-server
(.venv)$ markdownserver
Bottle v0.12.8 server starting up (using WSGIRefServer())...
Listening on http://localhost:8009/
$ open http://localhost:8009/sample.md

MarkdownServer CLI
------------------

If server start up successfully, browse below URL and check the converted result.
You can run the `markdownserver` command to start the server with the following examples:

### Example 1: Using Default Arguments
::

$ open http://localhost:8009/sample.md
(.venv)$ markdownserver

This will run the server on the default host (`localhost`) and port (`8009`), with debugging disabled.

### Example 2: Custom Host, Port, and Debug
::

(.venv)$ markdownserver --host 0.0.0.0 --port 8080 --debug

This will run the server on `0.0.0.0:8080` with debugging enabled, allowing you to access the server from any device on your local network.

**Arguments:**
- `--host`: Specify the host to run the server on (default is `localhost`).
- `--port`: Specify the port to run the server on (default is `8009`).
- `--debug`: Enable or disable debugging mode (default is `False`).

Only Conversion
---------------

Additionally, You can use the conversion function alone.
Additionally, you can use the conversion function alone from the command line.

::

(.venv)$ markdownconvert source_md_file target_html_file

This will convert the provided markdown file (`source_md_file`) into an HTML file (`target_html_file`).

MarkdownConverter CLI
---------------------

The `markdownconvert` command can be used with the following options:

::

(.venv)$ convert source_md_file target_html_file
$ markdownconvert source_md_file target_html_file

**Arguments:**
- `source_md_file`: The markdown file you want to convert to HTML.
- `target_html_file`: The output HTML file to save the converted content.

Example:

::

$ markdownconvert sample.md sample.md.html

This will convert the `sample.md` file into a `sample.md.html` file in the current directory.

--------------
Do as you like
--------------

- Markdown server purvey `http://host/[file_name]` URL. This corresponds to `resources/markdown/[file_name]`.You can put any markdown file here.

- Converted file will be placed to `resources/html` directory. Generated html file includes CSS so it's ease to distribute.

- Environment variables like *host name* or *port number* are set in `env.py`. Edit arbitrarily.
- The Markdown server provides `http://host/[file_name]` URL. You can place any markdown file here.

::
- The converted HTML file will be placed in the `resources/html` directory. The generated HTML file includes CSS for easy distribution.

ms_port = '8009'
ms_host = 'localhost'
Developers Information
======================

1. **Masato Ohba**
- GitHub: `@ohbarye <https://github.com/ohbarye>`
.. image:: https://avatars.githubusercontent.com/u/1811616
:alt: "Masato Ohba"
:width: 200px

- The default markdown engine is Github flavored Markdown. If you want to use another style, add CSS and edit `env.py`.
2. **Pt. Prashant Tripathi**
- GitHub: `@ptprashanttripathi <https://github.com/ptprashanttripathi>`
.. image:: https://avatars.githubusercontent.com/u/26687933
:alt: "Pt. Prashant Tripathi"
:width: 200px

::

css_name = 'github.css'
markdown_type = 'gfm'
Binary file added markdownserver-logo.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 6 additions & 30 deletions markdownserver/__init__.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,8 @@
from __future__ import absolute_import
from bottle import route, run, static_file
from .markdown_converter import MarkdownConverter
from .env import root_path, ms_host, ms_port, ms_debug
import os
from .markdown_server import MarkdownServer

converter = MarkdownConverter()


@route(r'/<resource:re:.*\.md>')
def gfmize(resource):
if resource == 'favicon.ico':
return ''

html_file_name = os.path.basename(converter.convert(resource))
if '/' in resource:
html_file_name = '/'.join(resource.split('/')[:-1]) + \
'/' + html_file_name
return static_file(os.path.join('resources/html',
html_file_name),
root=root_path)


def main():
run(host=ms_host,
port=ms_port,
debug=ms_debug,
reloader=False)


if __name__ == '__main__':
main()
__author__ = [
{"name": "Masato Ohba", "email": "[email protected]"},
{"name": "Pt. Prashant Tripathi", "email": "[email protected]"},
]
__all__ = ["MarkdownServer", "MarkdownConverter"]
51 changes: 33 additions & 18 deletions markdownserver/markdown_converter.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
from __future__ import print_function
from __future__ import absolute_import
from builtins import object
import markdown as md
import codecs
import sys
import os
from .env import css_path, ms_encoding, markdown_type, \
html_dir, html_extension
import markdown as md
import codecs
import argparse
from markdownserver.env import css_path, ms_encoding, markdown_type, html_dir, html_extension


class MarkdownConverter(object):
class MarkdownConverter:
def __init__(self):
"""Initialize the converter with the CSS header and footer."""
css = codecs.open(css_path, encoding=ms_encoding, mode="r")
self.html_header = (
"""
Expand All @@ -35,21 +33,21 @@ def __init__(self):
"""

def convert(self, src, dst=""):
"""Convert a Markdown file to HTML."""
code = md.markdown(self.read_md(src), extensions=[markdown_type])
return self.write_html(code, src, dst)

def read_md(self, file_name):
"""Read the contents of a Markdown file."""
workingdir = os.getcwd()
md_file = codecs.open(
os.path.join(workingdir, file_name),
encoding=ms_encoding,
mode="r"
os.path.join(workingdir, file_name), encoding=ms_encoding, mode="r"
)
return md_file.read()

def write_html(self, body, file_name, dst):
"""Write HTML content to a file."""
html_path = os.path.join(html_dir, file_name + html_extension)

if dst != "":
html_path = dst
try:
Expand All @@ -63,12 +61,29 @@ def write_html(self, body, file_name, dst):


def main():
args = sys.argv
if len(args) != 3:
print("usage: convert source_md_file target_html_file")
else:
converter = MarkdownConverter()
converter.convert(args[1], args[2])
"""CLI entry point to convert a Markdown file to HTML using argparse."""
parser = argparse.ArgumentParser(
description="Convert a Markdown file to an HTML file with styling."
)
parser.add_argument(
"source_md_file",
metavar="SOURCE_MD_FILE",
help="The source Markdown file to convert",
)
parser.add_argument(
"target_html_file",
metavar="TARGET_HTML_FILE",
help="The destination HTML file to save",
)

args = parser.parse_args()

# Convert the given Markdown file to HTML
converter = MarkdownConverter()
html_path = converter.convert(args.source_md_file, args.target_html_file)
print(
f"Markdown file '{args.source_md_file}' converted to HTML and saved as '{html_path}'"
)


if __name__ == "__main__":
Expand Down
122 changes: 122 additions & 0 deletions markdownserver/markdown_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import os
from http.server import SimpleHTTPRequestHandler, HTTPServer
from markdownserver.markdown_converter import MarkdownConverter
from markdownserver.env import ms_host, ms_port, ms_debug


class MarkdownServerHandler(SimpleHTTPRequestHandler):
"""
Custom HTTP request handler that dynamically converts Markdown (.md) files to HTML
when accessed via a browser. Non-Markdown files are served as-is.
"""

def do_GET(self):
"""
Handle GET requests.
- If the requested file is a Markdown file, convert it to HTML and serve it.
- Otherwise, serve the file normally.
"""
# Get the file path
filepath = self.translate_path(self.path)

# Check if the requested file is a Markdown file
if os.path.isfile(filepath) and filepath.endswith(".md"):
self.serve_markdown(filepath)
else:
super().do_GET()

def serve_markdown(self, filepath):
"""
Serve a Markdown file as HTML content.

Args:
filepath (str): The path to the Markdown file.
"""
try:
# Create an instance of the MarkdownConverter
converter = MarkdownConverter()

# Convert the Markdown file to HTML
html_path = converter.convert(filepath)

# Read the generated HTML content
with open(html_path, "r", encoding="utf-8") as html_file:
html_content = html_file.read()

# Send the response headers
self.send_response(200)
self.send_header("Content-type", "text/html; charset=utf-8")
self.end_headers()

# Write the HTML content to the response
self.wfile.write(html_content.encode("utf-8"))

except Exception as e:
self.send_error(500, f"Error processing Markdown file: {e}")


class MarkdownServer:
"""
A simple HTTP server for serving files, with special handling for Markdown files.
"""

def __init__(self, host=None, port=None, debug=False):
"""
Initialize the server.

Args:
host (str): Hostname to bind the server to. Default is 'localhost'.
port (int): Port to bind the server to. Default is 8000.
debug (bool): Enable/Disable debug mode. Default is False.
"""
# Use environment variables or defaults for host and port
self.host = host or ms_host
self.port = int(port or ms_port)
self.debug = debug or ms_debug
self.server_address = (self.host, self.port)
self.httpd = HTTPServer(self.server_address, MarkdownServerHandler)

def start(self):
"""
Start the HTTP server and begin serving requests.
"""
print(f"Markdown server is running on http://{self.host}:{self.port}")
self.httpd.serve_forever()

def stop(self):
"""
Stop the HTTP server.
"""
print("Shutting down the server...")
self.httpd.server_close()


def main():
"""
Main function to run the server with command-line arguments for host, port, and debug.
"""
import argparse

# Setup CLI arguments
parser = argparse.ArgumentParser(description="Start the markdown HTTP server.")
parser.add_argument("--host", help="Host to bind the server (default: localhost)")
parser.add_argument(
"--port", type=int, help="Port to bind the server (default: 8000)"
)
parser.add_argument(
"--debug", action="store_true", help="Enable debug mode (default: False)"
)

args = parser.parse_args()

# Create an instance of the server with provided or default arguments
server = MarkdownServer(host=args.host, port=args.port, debug=args.debug)

try:
server.start()
except KeyboardInterrupt:
server.stop()


if __name__ == "__main__":
main()
Loading