@udx/md2html 1.1.0 ā 1.2.0
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.
- package/index.js +99 -8
- package/package.json +4 -2
package/index.js
CHANGED
|
@@ -50,6 +50,9 @@ import { marked } from 'marked';
|
|
|
50
50
|
import { program } from 'commander';
|
|
51
51
|
import chokidar from 'chokidar';
|
|
52
52
|
import Handlebars from 'handlebars';
|
|
53
|
+
import express from 'express';
|
|
54
|
+
import { createServer } from 'http';
|
|
55
|
+
import open from 'open';
|
|
53
56
|
|
|
54
57
|
// Custom renderer for handling math blocks
|
|
55
58
|
const renderer = new marked.Renderer();
|
|
@@ -86,24 +89,41 @@ const CHAPTER_NAV_STYLES_PATH = path.join(path.dirname(new URL(import.meta.url).
|
|
|
86
89
|
const SCRIPTS_PATH = path.join(path.dirname(new URL(import.meta.url).pathname), 'static/scripts.js');
|
|
87
90
|
|
|
88
91
|
program
|
|
89
|
-
.version('1.
|
|
92
|
+
.version('1.2.0')
|
|
90
93
|
.description('Convert markdown files to a single HTML document with Google Docs styling')
|
|
91
|
-
.option('-s, --src <
|
|
92
|
-
.option('-o, --out <file>', 'Output HTML file path')
|
|
94
|
+
.option('-s, --src <file>', 'Source markdown file or directory')
|
|
95
|
+
.option('-o, --out <file>', 'Output HTML file path (optional - defaults to ./output.html)')
|
|
93
96
|
.option('-w, --watch', 'Watch for changes and rebuild automatically', false)
|
|
94
97
|
.option('-d, --debug', 'Enable debug logging', false)
|
|
98
|
+
.option('-p, --preview', 'Open generated HTML in browser with live preview server', false)
|
|
99
|
+
.option('--port <number>', 'Port for preview server (default: random)', parseInt)
|
|
100
|
+
.addHelpText('after', `
|
|
101
|
+
Examples:
|
|
102
|
+
Basic conversion:
|
|
103
|
+
md2html -s content/docs
|
|
104
|
+
md2html --src=content/docs --out=output.html
|
|
105
|
+
|
|
106
|
+
Watch mode:
|
|
107
|
+
md2html -s content/docs --watch
|
|
108
|
+
|
|
109
|
+
Browser preview:
|
|
110
|
+
md2html -s content/docs --preview
|
|
111
|
+
md2html -s content/docs --preview --port 3000
|
|
112
|
+
|
|
113
|
+
Single file:
|
|
114
|
+
md2html -s document.md --preview`)
|
|
95
115
|
.parse(process.argv);
|
|
96
116
|
|
|
97
117
|
const options = program.opts();
|
|
98
118
|
|
|
99
|
-
if (!options.src
|
|
100
|
-
console.error('Error: Source
|
|
119
|
+
if (!options.src) {
|
|
120
|
+
console.error('Error: Source markdown file or directory is required');
|
|
101
121
|
program.help();
|
|
102
122
|
process.exit(1);
|
|
103
123
|
}
|
|
104
124
|
|
|
105
125
|
const srcPath = path.resolve(options.src);
|
|
106
|
-
const outputFile = path.resolve(options.out);
|
|
126
|
+
const outputFile = options.out ? path.resolve(options.out) : path.resolve('./output.html');
|
|
107
127
|
|
|
108
128
|
const debug = (message) => {
|
|
109
129
|
if (options.debug) {
|
|
@@ -647,6 +667,57 @@ async function buildHtml(srcDir, outputFile) {
|
|
|
647
667
|
}
|
|
648
668
|
}
|
|
649
669
|
|
|
670
|
+
/**
|
|
671
|
+
* Gets a random port between 3000-9999
|
|
672
|
+
*/
|
|
673
|
+
function getRandomPort() {
|
|
674
|
+
return Math.floor(Math.random() * (9999 - 3000 + 1)) + 3000;
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
/**
|
|
678
|
+
* Starts a preview server for the generated HTML
|
|
679
|
+
* @param {string} outputFile - Path to the HTML file to serve
|
|
680
|
+
* @param {number|null} port - Port to use (null for random)
|
|
681
|
+
* @returns {Promise<number>} The port the server is running on
|
|
682
|
+
*/
|
|
683
|
+
function startPreviewServer(outputFile, port = null) {
|
|
684
|
+
return new Promise((resolve, reject) => {
|
|
685
|
+
const app = express();
|
|
686
|
+
const targetPort = port || getRandomPort();
|
|
687
|
+
|
|
688
|
+
// Serve the generated HTML file at root
|
|
689
|
+
app.get('/', (req, res) => {
|
|
690
|
+
if (!fs.existsSync(outputFile)) {
|
|
691
|
+
res.status(404).send('<h1>HTML file not found</h1><p>Try rebuilding first</p>');
|
|
692
|
+
return;
|
|
693
|
+
}
|
|
694
|
+
res.sendFile(path.resolve(outputFile));
|
|
695
|
+
});
|
|
696
|
+
|
|
697
|
+
// Serve any static assets if they exist
|
|
698
|
+
const staticDir = path.join(path.dirname(outputFile), 'assets');
|
|
699
|
+
if (fs.existsSync(staticDir)) {
|
|
700
|
+
app.use('/assets', express.static(staticDir));
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
const server = createServer(app);
|
|
704
|
+
|
|
705
|
+
server.listen(targetPort, () => {
|
|
706
|
+
console.log(`š Preview server running at http://localhost:${targetPort}`);
|
|
707
|
+
resolve(targetPort);
|
|
708
|
+
});
|
|
709
|
+
|
|
710
|
+
server.on('error', (err) => {
|
|
711
|
+
if (err.code === 'EADDRINUSE' && !port) {
|
|
712
|
+
// If random port is in use, try another random port
|
|
713
|
+
startPreviewServer(outputFile, null).then(resolve).catch(reject);
|
|
714
|
+
} else {
|
|
715
|
+
reject(err);
|
|
716
|
+
}
|
|
717
|
+
});
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
|
|
650
721
|
/**
|
|
651
722
|
* Watches for changes in markdown files and rebuilds HTML
|
|
652
723
|
* @param {string} srcDir - Source directory containing markdown files
|
|
@@ -730,8 +801,28 @@ function watchMarkdown(srcDir, outputFile) {
|
|
|
730
801
|
});
|
|
731
802
|
}
|
|
732
803
|
|
|
733
|
-
//
|
|
734
|
-
if (options.
|
|
804
|
+
// Handle different execution modes
|
|
805
|
+
if (options.preview) {
|
|
806
|
+
// Preview mode: build HTML, start server, and optionally watch
|
|
807
|
+
buildHtml(srcPath, outputFile).then((success) => {
|
|
808
|
+
if (success) {
|
|
809
|
+
startPreviewServer(outputFile, options.port).then((port) => {
|
|
810
|
+
// Open browser
|
|
811
|
+
open(`http://localhost:${port}`);
|
|
812
|
+
|
|
813
|
+
if (options.watch) {
|
|
814
|
+
console.log('\nš Watching for file changes...');
|
|
815
|
+
watchMarkdown(srcPath, outputFile);
|
|
816
|
+
} else {
|
|
817
|
+
console.log('\nš” Use --watch flag to auto-rebuild on file changes');
|
|
818
|
+
console.log('Press Ctrl+C to stop the server');
|
|
819
|
+
}
|
|
820
|
+
}).catch((err) => {
|
|
821
|
+
console.error('Failed to start preview server:', err);
|
|
822
|
+
});
|
|
823
|
+
}
|
|
824
|
+
});
|
|
825
|
+
} else if (options.watch) {
|
|
735
826
|
watchMarkdown(srcPath, outputFile);
|
|
736
827
|
} else {
|
|
737
828
|
buildHtml(srcPath, outputFile);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@udx/md2html",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Magazine-quality Markdown to HTML converter with professional styling",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -34,8 +34,10 @@
|
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"chokidar": "^3.5.3",
|
|
36
36
|
"commander": "^11.0.0",
|
|
37
|
+
"express": "^4.18.2",
|
|
37
38
|
"handlebars": "^4.7.8",
|
|
38
|
-
"marked": "^9.1.0"
|
|
39
|
+
"marked": "^9.1.0",
|
|
40
|
+
"open": "^9.1.0"
|
|
39
41
|
},
|
|
40
42
|
"engines": {
|
|
41
43
|
"node": ">=14.16"
|