Files
MarkdownRender/index.js
T
Cédric OLIVIER 85f62bf842 feat: change css + watcher
Signed-off-by: Cédric OLIVIER <olivier.cedric@gmail.com>
2026-06-19 12:08:45 +02:00

153 lines
4.9 KiB
JavaScript
Executable File

#!/usr/bin/env node
'use strict';
const path = require('path');
const fs = require('fs');
const minimist = require('minimist');
const { convert, buildIndex } = require('./lib/converter');
const { startServer } = require('./lib/server');
const { startWatcher } = require('./lib/watcher');
const argv = minimist(process.argv.slice(2), {
alias: { o: 'output', p: 'port', w: 'watch', v: 'preview', h: 'help' },
default: { port: 3000 },
boolean: ['watch', 'preview', 'open', 'help'],
});
if (argv.help) {
console.log(`
Usage: md-render <fichier.md|dossier> [options]
Options:
-w, --watch Surveille les modifications et recharge automatiquement
-v, --preview Comme --watch, mais ouvre aussi le navigateur
--open Ouvre le navigateur (combinable avec --watch)
-p, --port <port> Port du serveur (défaut: 3000)
-o, --output <dir> Dossier de sortie HTML (mode dossier, sans --watch)
-h, --help Affiche cette aide
Exemples:
md-render README.md Convertit README.md → README.html
md-render README.md --watch Live reload sur localhost:3000
md-render README.md --watch --open Live reload + ouvre le navigateur
md-render README.md --preview Alias de --watch --open
md-render ../my-portal.wiki/ Convertit tous les .md du dossier
md-render ../my-portal.wiki/ --watch Wiki live sur localhost:3000
`);
process.exit(0);
}
const input = argv._[0];
if (!input) {
console.error('\n✗ Erreur : veuillez fournir un fichier ou un dossier en argument.');
console.error(' Aide : md-render --help\n');
process.exit(1);
}
const absInput = path.resolve(input);
if (!fs.existsSync(absInput)) {
console.error(`\n✗ Erreur : introuvable : ${absInput}\n`);
process.exit(1);
}
const stat = fs.statSync(absInput);
const isDir = stat.isDirectory();
// ── SERVER MODE (--watch ou --preview) ──────────────────────────────────────
if (argv.watch || argv.preview) {
const port = parseInt(argv.port, 10);
if (isNaN(port) || port < 1 || port > 65535) {
console.error(`\n✗ Erreur : port invalide "${argv.port}".\n`);
process.exit(1);
}
const shouldOpen = argv.preview || argv.open;
function openBrowser(url) {
const { exec } = require('child_process');
const cmd =
process.platform === 'darwin' ? `open "${url}"` :
process.platform === 'win32' ? `start "" "${url}"` :
`xdg-open "${url}"`;
exec(cmd, (err) => {
if (err) console.warn(` ⚠ Impossible d'ouvrir le navigateur : ${err.message}`);
});
}
const serverObj = startServer({
inputFile: isDir ? null : absInput,
inputDir: isDir ? absInput : null,
port,
onReady: shouldOpen ? (p) => {
console.log(' Appuyez sur Ctrl+C pour arrêter.\n');
openBrowser(`http://localhost:${p}`);
} : null,
});
startWatcher({
inputFile: isDir ? null : absInput,
inputDir: isDir ? absInput : null,
server: serverObj,
});
process.on('SIGINT', () => {
serverObj.server.close();
console.log('\n👋 Au revoir !');
process.exit(0);
});
return;
}
// ── ONE-SHOT MODE ────────────────────────────────────────────────────────────
if (isDir) {
// Convert all .md files in the directory
const outputDir = argv.output ? path.resolve(argv.output) : absInput;
const files = findMarkdownFilesSync(absInput);
if (files.length === 0) {
console.error(`\n✗ Aucun fichier .md trouvé dans : ${absInput}\n`);
process.exit(1);
}
let ok = 0;
files.forEach((f) => {
try {
const rel = path.relative(absInput, f).replace(/\.md$/i, '.html');
const outFile = path.join(outputDir, rel);
fs.mkdirSync(path.dirname(outFile), { recursive: true });
fs.writeFileSync(outFile, convert(f, false), 'utf-8');
console.log(`${rel}`);
ok++;
} catch (err) {
console.error(`${path.relative(absInput, f)}${err.message}`);
}
});
console.log(`\n${ok}/${files.length} fichier(s) converti(s).`);
} else {
const outputFile = argv.output
? path.resolve(argv.output)
: absInput.replace(/\.md$/i, '.html');
try {
fs.writeFileSync(outputFile, convert(absInput, false), 'utf-8');
console.log(`✓ Converti : ${outputFile}`);
} catch (err) {
console.error(`\n✗ Erreur de conversion : ${err.message}\n`);
process.exit(1);
}
}
function findMarkdownFilesSync(dir) {
const results = [];
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
if (entry.name.startsWith('.')) continue;
const full = path.join(dir, entry.name);
if (entry.isDirectory()) results.push(...findMarkdownFilesSync(full));
else if (/\.md$/i.test(entry.name)) results.push(full);
}
return results;
}