mdviewer 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,153 @@
1
+ Metadata-Version: 2.4
2
+ Name: mdviewer
3
+ Version: 0.2.0
4
+ Summary: GitHub-style Markdown viewer
5
+ Author-email: Biao Jiang <github@minsignal.com>
6
+ License: MIT
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: flask
9
+ Requires-Dist: livereload
10
+ Requires-Dist: markdown-it-py
11
+ Requires-Dist: beautifulsoup4
12
+
13
+ # 📝 Markdown Viewer (GitHub-Style)
14
+
15
+ [![PyPI](https://img.shields.io/pypi/v/mdviewer.svg)](https://pypi.org/project/mdviewer)
16
+ [![Homebrew](https://img.shields.io/badge/Homebrew-mdviewer-blue)](https://github.com/yourusername/homebrew-mdviewer)
17
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
18
+
19
+ A GitHub-style Markdown viewer for local docs, with file tree, search, and live reload.
20
+
21
+ A local Markdown documentation browser that:
22
+
23
+ - Renders `.md` files with GitHub-flavored styles
24
+ - Displays a recursive file/folder tree
25
+ - Supports live plain-text filtering (client-side)
26
+ - Supports filename/content search using `fd` or `rg`
27
+ - Auto-reloads edited files
28
+ - Dark/light mode toggle
29
+ - Export/Print to PDF
30
+ - Breadcrumb navigation with folder/file icons
31
+ - Highlights current file in tree and auto-expands
32
+
33
+ ## 🚀 Installation
34
+
35
+ ### 🔧 Option 1: Homebrew (macOS/Linux)
36
+
37
+ ```bash
38
+ brew tap biaojiang/mdviewer
39
+ brew install mdviewer
40
+ ```
41
+
42
+ ### 🐍 Option 2: Python (via pip)
43
+
44
+ ```
45
+ pip install mdviewer
46
+ ```
47
+
48
+ **Optionally add an alias:**
49
+
50
+ ```bash
51
+ echo 'alias mdv="mdviewer"' >> ~/.zshrc
52
+ source ~/.zshrc
53
+ # or symlink
54
+ sudo ln -s $(which mdviewer) /usr/local/bin/mdv
55
+ ```
56
+
57
+ ### 🔧 Option 3: Build from Source
58
+
59
+ ```sh
60
+ # Install Python deps
61
+ pip install -r requirements.txt
62
+
63
+ # Optional: use a venv
64
+ python -m venv .venv
65
+ source .venv/bin/activate
66
+
67
+ # Install tools if needing advanced search
68
+ brew install fd ripgrep
69
+ # or
70
+ sudo apt install fd-find ripgrep
71
+
72
+ # ▶️ Run the Server
73
+ python app.py
74
+
75
+ Open [http://127.0.0.1:5000](http://127.0.0.1:5000/) in your browser.
76
+ ```
77
+
78
+ ---
79
+
80
+ ## 🚀 Features
81
+
82
+ - ✅ GitHub-style rendering via `markdown-it-py` + GitHub CSS
83
+ - ✅ Auto-expandable file tree using `<details>`
84
+ - ✅ Live filtering with reset button
85
+ - ✅ Backend-powered search:
86
+ - `fd`: fuzzy filename matching
87
+ - `rg`: content search
88
+ - ✅ Flask-based local webserver
89
+ - ✅ MathJax support for LaTeX
90
+ - ✅ Reload current buffer on changes (with `livereload`)
91
+ - ✅ Font Awesome icons for folders/files
92
+ - ✅ Breadcrumb that reflects navigation path
93
+ - ✅ Highlight + auto-expand tree for active file
94
+ - ✅ PDF/Print export button with clean print CSS
95
+
96
+ ---
97
+
98
+ ## 📁 File Structure
99
+
100
+ ```text
101
+ .
102
+ ├── docs
103
+ │ └── math
104
+ │ └── math-test.md
105
+ ├── pyproject.toml
106
+ ├── README.md
107
+ ├── requirements.txt
108
+ ├── screenshot.png
109
+ ├── src
110
+ │ ├── mdviewer
111
+ │ │ ├── __init__.py
112
+ │ │ ├── app.py
113
+ │ │ ├── cli.py
114
+ │ │ └── search
115
+ ├── static
116
+ │ ├── script.js
117
+ │ └── style.css
118
+ └── templates
119
+ ├── index.html
120
+ ├── search.html
121
+ └── viewer.html
122
+ ```
123
+
124
+ ---
125
+
126
+ ## 🔍 Search Modes
127
+
128
+ - `fd`: fuzzy filename match (fast)
129
+ - `rg`: full-text content match (powerful)
130
+
131
+ ---
132
+
133
+ ## ⚙️ Keyboard & UI
134
+
135
+ - 🌓 Dark/light toggle
136
+ - ⌨️ Live tree filter with reset
137
+ - 🗂 Expandable nested folders
138
+ - 🔗 Click to render `.md` file in browser
139
+ - 🖨 Export/Print to PDF button
140
+ - 📁 Breadcrumb with Font Awesome icons
141
+ - 📄 Highlight + expand tree for active file
142
+
143
+ ---
144
+
145
+ ## ⏭️ Next Steps
146
+
147
+ -
148
+
149
+ ---
150
+
151
+ ## 📄 License
152
+
153
+ MIT
@@ -0,0 +1,141 @@
1
+ # 📝 Markdown Viewer (GitHub-Style)
2
+
3
+ [![PyPI](https://img.shields.io/pypi/v/mdviewer.svg)](https://pypi.org/project/mdviewer)
4
+ [![Homebrew](https://img.shields.io/badge/Homebrew-mdviewer-blue)](https://github.com/yourusername/homebrew-mdviewer)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
6
+
7
+ A GitHub-style Markdown viewer for local docs, with file tree, search, and live reload.
8
+
9
+ A local Markdown documentation browser that:
10
+
11
+ - Renders `.md` files with GitHub-flavored styles
12
+ - Displays a recursive file/folder tree
13
+ - Supports live plain-text filtering (client-side)
14
+ - Supports filename/content search using `fd` or `rg`
15
+ - Auto-reloads edited files
16
+ - Dark/light mode toggle
17
+ - Export/Print to PDF
18
+ - Breadcrumb navigation with folder/file icons
19
+ - Highlights current file in tree and auto-expands
20
+
21
+ ## 🚀 Installation
22
+
23
+ ### 🔧 Option 1: Homebrew (macOS/Linux)
24
+
25
+ ```bash
26
+ brew tap biaojiang/mdviewer
27
+ brew install mdviewer
28
+ ```
29
+
30
+ ### 🐍 Option 2: Python (via pip)
31
+
32
+ ```
33
+ pip install mdviewer
34
+ ```
35
+
36
+ **Optionally add an alias:**
37
+
38
+ ```bash
39
+ echo 'alias mdv="mdviewer"' >> ~/.zshrc
40
+ source ~/.zshrc
41
+ # or symlink
42
+ sudo ln -s $(which mdviewer) /usr/local/bin/mdv
43
+ ```
44
+
45
+ ### 🔧 Option 3: Build from Source
46
+
47
+ ```sh
48
+ # Install Python deps
49
+ pip install -r requirements.txt
50
+
51
+ # Optional: use a venv
52
+ python -m venv .venv
53
+ source .venv/bin/activate
54
+
55
+ # Install tools if needing advanced search
56
+ brew install fd ripgrep
57
+ # or
58
+ sudo apt install fd-find ripgrep
59
+
60
+ # ▶️ Run the Server
61
+ python app.py
62
+
63
+ Open [http://127.0.0.1:5000](http://127.0.0.1:5000/) in your browser.
64
+ ```
65
+
66
+ ---
67
+
68
+ ## 🚀 Features
69
+
70
+ - ✅ GitHub-style rendering via `markdown-it-py` + GitHub CSS
71
+ - ✅ Auto-expandable file tree using `<details>`
72
+ - ✅ Live filtering with reset button
73
+ - ✅ Backend-powered search:
74
+ - `fd`: fuzzy filename matching
75
+ - `rg`: content search
76
+ - ✅ Flask-based local webserver
77
+ - ✅ MathJax support for LaTeX
78
+ - ✅ Reload current buffer on changes (with `livereload`)
79
+ - ✅ Font Awesome icons for folders/files
80
+ - ✅ Breadcrumb that reflects navigation path
81
+ - ✅ Highlight + auto-expand tree for active file
82
+ - ✅ PDF/Print export button with clean print CSS
83
+
84
+ ---
85
+
86
+ ## 📁 File Structure
87
+
88
+ ```text
89
+ .
90
+ ├── docs
91
+ │ └── math
92
+ │ └── math-test.md
93
+ ├── pyproject.toml
94
+ ├── README.md
95
+ ├── requirements.txt
96
+ ├── screenshot.png
97
+ ├── src
98
+ │ ├── mdviewer
99
+ │ │ ├── __init__.py
100
+ │ │ ├── app.py
101
+ │ │ ├── cli.py
102
+ │ │ └── search
103
+ ├── static
104
+ │ ├── script.js
105
+ │ └── style.css
106
+ └── templates
107
+ ├── index.html
108
+ ├── search.html
109
+ └── viewer.html
110
+ ```
111
+
112
+ ---
113
+
114
+ ## 🔍 Search Modes
115
+
116
+ - `fd`: fuzzy filename match (fast)
117
+ - `rg`: full-text content match (powerful)
118
+
119
+ ---
120
+
121
+ ## ⚙️ Keyboard & UI
122
+
123
+ - 🌓 Dark/light toggle
124
+ - ⌨️ Live tree filter with reset
125
+ - 🗂 Expandable nested folders
126
+ - 🔗 Click to render `.md` file in browser
127
+ - 🖨 Export/Print to PDF button
128
+ - 📁 Breadcrumb with Font Awesome icons
129
+ - 📄 Highlight + expand tree for active file
130
+
131
+ ---
132
+
133
+ ## ⏭️ Next Steps
134
+
135
+ -
136
+
137
+ ---
138
+
139
+ ## 📄 License
140
+
141
+ MIT
@@ -0,0 +1,23 @@
1
+ [build-system]
2
+ requires = ["setuptools>=80.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "mdviewer"
7
+ version = "0.2.0"
8
+ description = "GitHub-style Markdown viewer"
9
+ readme = "README.md"
10
+ authors = [{ name = "Biao Jiang", email = "github@minsignal.com" }]
11
+ license = { text = "MIT" }
12
+ dependencies = [
13
+ "flask",
14
+ "livereload",
15
+ "markdown-it-py",
16
+ "beautifulsoup4"
17
+ ]
18
+
19
+ [project.scripts]
20
+ mdviewer = "mdviewer.cli:main"
21
+
22
+ [tool.setuptools.packages.find]
23
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
File without changes
@@ -0,0 +1,159 @@
1
+ import os
2
+
3
+ from bs4 import BeautifulSoup
4
+ from flask import Flask, abort, render_template, request, send_from_directory
5
+ from livereload import Server
6
+ from markdown_it import MarkdownIt
7
+
8
+ from mdviewer.search.fd_search import search_filenames
9
+ from mdviewer.search.rg_search import search_content
10
+
11
+ BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
12
+
13
+ app = Flask(
14
+ __name__,
15
+ template_folder=os.path.join(BASE_DIR, "templates"),
16
+ static_folder=os.path.join(BASE_DIR, "static"),
17
+ )
18
+ md = MarkdownIt()
19
+ MARKDOWN_ROOT = os.path.abspath(".")
20
+ EXCLUDED_DIRS = {'.git', '.venv', '__pycache__', 'node_modules', '.ruff_cache'}
21
+
22
+
23
+ # build_tree function to create a directory tree
24
+ def build_tree(root_dir):
25
+ tree = {}
26
+ for dirpath, dirnames, filenames in os.walk(root_dir):
27
+ rel_path = os.path.relpath(dirpath, root_dir)
28
+
29
+ # Exclude unwanted directories
30
+ dirnames[:] = [d for d in dirnames if d not in EXCLUDED_DIRS]
31
+
32
+ node = tree
33
+ if rel_path != ".":
34
+ for part in rel_path.split(os.sep):
35
+ node = node.setdefault(part, {})
36
+
37
+ for filename in filenames:
38
+ if filename.endswith(".md"):
39
+ node[filename] = os.path.relpath(
40
+ os.path.join(dirpath, filename), root_dir
41
+ )
42
+ return tree
43
+
44
+
45
+ # Flask routes
46
+ @app.route("/")
47
+ def index():
48
+ file_tree = build_tree(MARKDOWN_ROOT)
49
+ return render_template(
50
+ "index.html", tree=file_tree, initial_file=app.config.get("INITIAL_FILE")
51
+ )
52
+
53
+
54
+ @app.route("/files/<path:filepath>")
55
+ def serve_file(filepath):
56
+ full_path = os.path.join(MARKDOWN_ROOT, filepath)
57
+ if not os.path.isfile(full_path):
58
+ abort(404)
59
+ return send_from_directory(MARKDOWN_ROOT, filepath)
60
+
61
+
62
+ @app.route("/view/<path:filename>")
63
+ def view_markdown(filename):
64
+ full_path = os.path.abspath(os.path.join(MARKDOWN_ROOT, filename))
65
+
66
+ if not full_path.startswith(MARKDOWN_ROOT):
67
+ abort(403)
68
+
69
+ if os.path.isdir(full_path):
70
+ entries = []
71
+ for item in sorted(os.listdir(full_path)):
72
+ if item.startswith("."):
73
+ continue # Skip hidden files
74
+ item_path = os.path.join(filename, item)
75
+ if os.path.isdir(os.path.join(MARKDOWN_ROOT, item_path)):
76
+ entries.append((item + "/", item_path))
77
+ elif item.endswith(".md"):
78
+ entries.append((item, item_path))
79
+ return render_template(
80
+ "viewer.html",
81
+ folder=filename,
82
+ entries=entries,
83
+ content=None,
84
+ filename=filename,
85
+ )
86
+
87
+ elif os.path.isfile(full_path):
88
+ with open(full_path, encoding="utf-8") as f:
89
+ content_md = f.read()
90
+ html = md.render(content_md)
91
+
92
+ # Fix image paths
93
+ soup = BeautifulSoup(html, "html.parser")
94
+ for img in soup.find_all("img"):
95
+ src = img.get("src")
96
+ if src and not src.startswith("http") and not src.startswith("/files/"):
97
+ img_path = os.path.normpath(
98
+ os.path.join(os.path.dirname(filename), src)
99
+ )
100
+ img["src"] = f"/files/{img_path}"
101
+
102
+ return render_template(
103
+ "viewer.html", content=str(soup), entries=None, filename=filename
104
+ )
105
+
106
+ else:
107
+ abort(404)
108
+
109
+
110
+ # Search functionality
111
+ @app.route("/search")
112
+ def search():
113
+ query = request.args.get("q", "").strip()
114
+ mode = request.args.get("mode", "fd") # switch between fd or rg
115
+ results = []
116
+
117
+ if query:
118
+ if mode == "rg":
119
+ results = search_content(query, MARKDOWN_ROOT)
120
+ else:
121
+ results = search_filenames(query, MARKDOWN_ROOT)
122
+
123
+ return render_template("search.html", results=results, query=query, mode=mode)
124
+
125
+
126
+ def start_server(markdown_root, open_file=None):
127
+ global MARKDOWN_ROOT
128
+ MARKDOWN_ROOT = os.path.abspath(markdown_root)
129
+ app.config["INITIAL_FILE"] = open_file
130
+
131
+ server = Server(app.wsgi_app)
132
+
133
+ # 🔁 Watch templates, static files, and markdown
134
+ server.watch("templates/**/*.html")
135
+ server.watch("static/**/*.js")
136
+ server.watch("static/**/*.css")
137
+ server.watch("**/*.md")
138
+
139
+ # print(f"🔄 Serving http://127.0.0.1:5000")
140
+ if open_file:
141
+ print(f"📄 Opening file: {open_file}")
142
+
143
+ server.serve(port=5000, host="127.0.0.1", debug=True)
144
+
145
+
146
+ if __name__ == "__main__":
147
+ server = Server(app.wsgi_app)
148
+
149
+ # Watch all .md files starting from the project root
150
+ server.watch("**/*.md")
151
+
152
+ # Watch template changes
153
+ server.watch("templates/*.html")
154
+
155
+ # Optionally watch static JS/CSS too
156
+ server.watch("static/*.js")
157
+ # server.watch("static/*.css")
158
+
159
+ server.serve(port=5000, debug=True)
@@ -0,0 +1,47 @@
1
+ import argparse
2
+ import os
3
+ import webbrowser
4
+ from mdviewer.app import start_server # make app.py expose a `start_server(path)`
5
+
6
+
7
+ def main():
8
+ parser = argparse.ArgumentParser(
9
+ prog="mdv", description="📘 mdviewer — GitHub-style Markdown viewer"
10
+ )
11
+ parser.add_argument(
12
+ "target", nargs="?", default="README.md", help="Markdown file or folder to view"
13
+ )
14
+ parser.add_argument(
15
+ "-o",
16
+ "--open",
17
+ action="store_true",
18
+ help="Open in browser after starting server (default: off)",
19
+ )
20
+
21
+ args = parser.parse_args()
22
+
23
+ # Expand ~ and resolve absolute path
24
+ target = os.path.abspath(os.path.expanduser(args.target))
25
+
26
+ if not os.path.exists(target):
27
+ print(f"❌ Error: Path not found: {target}")
28
+ return
29
+
30
+ # Determine root (folder) and optional file
31
+ root = target if os.path.isdir(target) else os.path.dirname(target)
32
+ open_file = target if os.path.isfile(target) else None
33
+
34
+ print(f"📂 Serving: {root}")
35
+
36
+ start_server(markdown_root=root, open_file=open_file)
37
+
38
+ print("🌐 Open in browser: http://127.0.0.1:5000")
39
+ print("🛑 Press Ctrl-C to stop server.")
40
+ print("❗ Remember to close the browser tab before restarting.")
41
+
42
+ if args.open:
43
+ webbrowser.open_new_tab("http://127.0.0.1:5000")
44
+
45
+
46
+ if __name__ == "__main__":
47
+ main()
File without changes
@@ -0,0 +1,16 @@
1
+ import subprocess
2
+ import os
3
+
4
+
5
+ def search_filenames(query, root):
6
+ try:
7
+ result = subprocess.run(
8
+ ["fd", "--type", "f", "--extension", "md", query, root],
9
+ capture_output=True,
10
+ text=True,
11
+ )
12
+ matches = result.stdout.strip().split("\n")
13
+ return [os.path.relpath(m, root) for m in matches if m]
14
+ except Exception as e:
15
+ print("[FD ERROR]", e)
16
+ return []
@@ -0,0 +1,16 @@
1
+ import subprocess
2
+ import os
3
+
4
+
5
+ def search_content(query, root):
6
+ try:
7
+ result = subprocess.run(
8
+ ["rg", "--files-with-matches", "-i", "-t", "md", query, root],
9
+ capture_output=True,
10
+ text=True,
11
+ )
12
+ matches = result.stdout.strip().split("\n")
13
+ return [os.path.relpath(m, root) for m in matches if m]
14
+ except Exception as e:
15
+ print("[RG ERROR]", e)
16
+ return []
@@ -0,0 +1,153 @@
1
+ Metadata-Version: 2.4
2
+ Name: mdviewer
3
+ Version: 0.2.0
4
+ Summary: GitHub-style Markdown viewer
5
+ Author-email: Biao Jiang <github@minsignal.com>
6
+ License: MIT
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: flask
9
+ Requires-Dist: livereload
10
+ Requires-Dist: markdown-it-py
11
+ Requires-Dist: beautifulsoup4
12
+
13
+ # 📝 Markdown Viewer (GitHub-Style)
14
+
15
+ [![PyPI](https://img.shields.io/pypi/v/mdviewer.svg)](https://pypi.org/project/mdviewer)
16
+ [![Homebrew](https://img.shields.io/badge/Homebrew-mdviewer-blue)](https://github.com/yourusername/homebrew-mdviewer)
17
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
18
+
19
+ A GitHub-style Markdown viewer for local docs, with file tree, search, and live reload.
20
+
21
+ A local Markdown documentation browser that:
22
+
23
+ - Renders `.md` files with GitHub-flavored styles
24
+ - Displays a recursive file/folder tree
25
+ - Supports live plain-text filtering (client-side)
26
+ - Supports filename/content search using `fd` or `rg`
27
+ - Auto-reloads edited files
28
+ - Dark/light mode toggle
29
+ - Export/Print to PDF
30
+ - Breadcrumb navigation with folder/file icons
31
+ - Highlights current file in tree and auto-expands
32
+
33
+ ## 🚀 Installation
34
+
35
+ ### 🔧 Option 1: Homebrew (macOS/Linux)
36
+
37
+ ```bash
38
+ brew tap biaojiang/mdviewer
39
+ brew install mdviewer
40
+ ```
41
+
42
+ ### 🐍 Option 2: Python (via pip)
43
+
44
+ ```
45
+ pip install mdviewer
46
+ ```
47
+
48
+ **Optionally add an alias:**
49
+
50
+ ```bash
51
+ echo 'alias mdv="mdviewer"' >> ~/.zshrc
52
+ source ~/.zshrc
53
+ # or symlink
54
+ sudo ln -s $(which mdviewer) /usr/local/bin/mdv
55
+ ```
56
+
57
+ ### 🔧 Option 3: Build from Source
58
+
59
+ ```sh
60
+ # Install Python deps
61
+ pip install -r requirements.txt
62
+
63
+ # Optional: use a venv
64
+ python -m venv .venv
65
+ source .venv/bin/activate
66
+
67
+ # Install tools if needing advanced search
68
+ brew install fd ripgrep
69
+ # or
70
+ sudo apt install fd-find ripgrep
71
+
72
+ # ▶️ Run the Server
73
+ python app.py
74
+
75
+ Open [http://127.0.0.1:5000](http://127.0.0.1:5000/) in your browser.
76
+ ```
77
+
78
+ ---
79
+
80
+ ## 🚀 Features
81
+
82
+ - ✅ GitHub-style rendering via `markdown-it-py` + GitHub CSS
83
+ - ✅ Auto-expandable file tree using `<details>`
84
+ - ✅ Live filtering with reset button
85
+ - ✅ Backend-powered search:
86
+ - `fd`: fuzzy filename matching
87
+ - `rg`: content search
88
+ - ✅ Flask-based local webserver
89
+ - ✅ MathJax support for LaTeX
90
+ - ✅ Reload current buffer on changes (with `livereload`)
91
+ - ✅ Font Awesome icons for folders/files
92
+ - ✅ Breadcrumb that reflects navigation path
93
+ - ✅ Highlight + auto-expand tree for active file
94
+ - ✅ PDF/Print export button with clean print CSS
95
+
96
+ ---
97
+
98
+ ## 📁 File Structure
99
+
100
+ ```text
101
+ .
102
+ ├── docs
103
+ │ └── math
104
+ │ └── math-test.md
105
+ ├── pyproject.toml
106
+ ├── README.md
107
+ ├── requirements.txt
108
+ ├── screenshot.png
109
+ ├── src
110
+ │ ├── mdviewer
111
+ │ │ ├── __init__.py
112
+ │ │ ├── app.py
113
+ │ │ ├── cli.py
114
+ │ │ └── search
115
+ ├── static
116
+ │ ├── script.js
117
+ │ └── style.css
118
+ └── templates
119
+ ├── index.html
120
+ ├── search.html
121
+ └── viewer.html
122
+ ```
123
+
124
+ ---
125
+
126
+ ## 🔍 Search Modes
127
+
128
+ - `fd`: fuzzy filename match (fast)
129
+ - `rg`: full-text content match (powerful)
130
+
131
+ ---
132
+
133
+ ## ⚙️ Keyboard & UI
134
+
135
+ - 🌓 Dark/light toggle
136
+ - ⌨️ Live tree filter with reset
137
+ - 🗂 Expandable nested folders
138
+ - 🔗 Click to render `.md` file in browser
139
+ - 🖨 Export/Print to PDF button
140
+ - 📁 Breadcrumb with Font Awesome icons
141
+ - 📄 Highlight + expand tree for active file
142
+
143
+ ---
144
+
145
+ ## ⏭️ Next Steps
146
+
147
+ -
148
+
149
+ ---
150
+
151
+ ## 📄 License
152
+
153
+ MIT
@@ -0,0 +1,14 @@
1
+ README.md
2
+ pyproject.toml
3
+ src/mdviewer/__init__.py
4
+ src/mdviewer/app.py
5
+ src/mdviewer/cli.py
6
+ src/mdviewer.egg-info/PKG-INFO
7
+ src/mdviewer.egg-info/SOURCES.txt
8
+ src/mdviewer.egg-info/dependency_links.txt
9
+ src/mdviewer.egg-info/entry_points.txt
10
+ src/mdviewer.egg-info/requires.txt
11
+ src/mdviewer.egg-info/top_level.txt
12
+ src/mdviewer/search/__init__.py
13
+ src/mdviewer/search/fd_search.py
14
+ src/mdviewer/search/rg_search.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ mdviewer = mdviewer.cli:main
@@ -0,0 +1,4 @@
1
+ flask
2
+ livereload
3
+ markdown-it-py
4
+ beautifulsoup4
@@ -0,0 +1 @@
1
+ mdviewer