AI生成的基于html+marked.js实现的Markdown转html工具,离线使用,可实时预览 [

发布于:2025-06-07 ⋅ 阅读:(16) ⋅ 点赞:(0)

有一个markdown格式的文档,手头只有notepad++的MarkdownPanel插件可以预览,但是只能预览,不能直接转换为html文件下载,直接复制预览的内效果又不太好,度娘也能找到很多工具,但是都需要在线使用。所以考虑用AI自己生成一个。
要求:可以离线使用,轻量,可以实时预览。
了解到marked.js是一个使用JavaScript实现的markdown解析库,功能比较完善,所以考虑使用html+js来实现markdown文档转换为html功能。
生成结果截图:

以下为生成步骤及最终源码:

1.在deepseek中输入要求:
使用html+marked.js实现Markdown转html功能,要求页面为左右布局,左侧输入markdown文本后右侧可以实时预览,预览效果应与下载的html页面打开后的展示内容一致

2.检查deepseek生成的代码,发现deepseek生成的源码中有两部分不是以源码的形式输出的,输出的是渲染后的结果

发现把示例代码中的引用快'''全部调整成了\'\'\',源码复制出来时候稍后手动修正

4.新增上传功能,以及调整按钮布局

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Markdown实时预览工具</title>
    <script src="marked.min.js"></script>
    <style>
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }
         
        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
            line-height: 1.6;
            color: #333;
            background-color: #f5f5f5;
            height: 100vh;
            display: flex;
            flex-direction: column;
        }
         
        .header {
            background-color: #2c3e50;
            color: white;
            padding: 15px 20px;
            text-align: center;
        }
         
        .container {
            display: flex;
            flex: 1;
            overflow: hidden;
        }
         
        .editor-pane, .preview-pane {
            flex: 1;
            padding: 20px;
            overflow-y: auto;
            height: 100%;
        }
         
        .editor-pane {
            background-color: #f8f9fa;
            border-right: 1px solid #ddd;
        }
         
        .preview-pane {
            background-color: white;
        }
         
        textarea {
            width: 100%;
            height: 100%;
            min-height: 300px;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 4px;
            resize: none;
            font-family: monospace;
            font-size: 14px;
            line-height: 1.5;
        }
         
        .preview-content {
            height: 100%;
            overflow-y: auto;
            padding: 10px;
        }
         
        .toolbar {
            padding: 10px 20px;
            background-color: #ecf0f1;
            border-bottom: 1px solid #ddd;
            display: flex;
            justify-content: space-between;
        }
         
        .left-toolbar, .right-toolbar {
            display: flex;
            gap: 10px;
        }
         
        button {
            padding: 8px 15px;
            background-color: #3498db;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 14px;
        }
         
        button:hover {
            background-color: #2980b9;
        }
         
        #file-input {
            display: none;
        }
         
        /* Markdown样式,确保预览和导出一致 */
        .markdown-body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
            line-height: 1.6;
            color: #333;
        }
         
        .markdown-body h1, .markdown-body h2, .markdown-body h3, .markdown-body h4, .markdown-body h5, .markdown-body h6 {
            margin-top: 24px;
            margin-bottom: 16px;
            font-weight: 600;
            line-height: 1.25;
        }
         
        .markdown-body h1 {
            padding-bottom: 0.3em;
            font-size: 2em;
            border-bottom: 1px solid #eaecef;
        }
         
        .markdown-body h2 {
            padding-bottom: 0.3em;
            font-size: 1.5em;
            border-bottom: 1px solid #eaecef;
        }
         
        .markdown-body p {
            margin-top: 0;
            margin-bottom: 16px;
        }
         
        .markdown-body a {
            color: #0366d6;
            text-decoration: none;
        }
         
        .markdown-body a:hover {
            text-decoration: underline;
        }
         
        .markdown-body code {
            font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace;
            padding: 0.2em 0.4em;
            margin: 0;
            font-size: 85%;
            background-color: rgba(27, 31, 35, 0.05);
            border-radius: 3px;
        }
         
        .markdown-body pre {
            background-color: #f6f8fa;
            border-radius: 3px;
            padding: 16px;
            overflow: auto;
            line-height: 1.45;
        }
         
        .markdown-body pre code {
            padding: 0;
            margin: 0;
            background-color: transparent;
            border-radius: 0;
        }
         
        .markdown-body blockquote {
            padding: 0 1em;
            color: #6a737d;
            border-left: 0.25em solid #dfe2e5;
            margin: 0 0 16px 0;
        }
         
        .markdown-body table {
            border-collapse: collapse;
            margin: 16px 0;
            width: 100%;
        }
         
        .markdown-body table th, .markdown-body table td {
            padding: 6px 13px;
            border: 1px solid #dfe2e5;
        }
         
        .markdown-body table tr {
            background-color: #fff;
            border-top: 1px solid #c6cbd1;
        }
         
        .markdown-body table tr:nth-child(2n) {
            background-color: #f6f8fa;
        }
         
        .markdown-body img {
            max-width: 100%;
        }
    </style>
</head>
<body>
    <div class="header">
        <h1>Markdown实时预览工具</h1>
    </div>
     
    <div class="toolbar">
        <div class="left-toolbar">
            <button id="upload-btn">上传Markdown文件</button>
            <input type="file" id="file-input" accept=".md,.markdown">
        </div>
        <div class="right-toolbar">
            <button id="download-btn">下载HTML</button>
        </div>
    </div>
     
    <div class="container">
        <div class="editor-pane">
            <textarea id="markdown-input" placeholder="在此输入Markdown文本..."># Markdown 实时预览工具
 
这是一个使用 **marked.js** 实现的Markdown实时预览工具。
 
## 功能特点
 
- 左右分栏布局
- 左侧编辑,右侧实时预览
- 预览效果与导出的HTML一致
- 支持常见的Markdown语法
 
### 代码示例
 
```javascript
function hello() {
    console.log("Hello, Markdown!");
}
```
 
### 表格示例
 
```
| 语法 | 描述 |
|------|------|
| 标题 | 使用 `#` |
| 列表 | 使用 `-` 或 `*` |
| 链接 | `[text](url)` |
```
 
> 提示:尝试在左侧编辑内容,右侧会实时更新预览效果。</textarea>
        </div>
         
        <div class="preview-pane">
            <div id="preview-content" class="preview-content markdown-body"></div>
        </div>
    </div>
     
    <script>
        // 获取DOM元素
        const markdownInput = document.getElementById('markdown-input');
        const previewContent = document.getElementById('preview-content');
        const downloadBtn = document.getElementById('download-btn');
        const uploadBtn = document.getElementById('upload-btn');
        const fileInput = document.getElementById('file-input');
         
        // 配置marked.js
        marked.setOptions({
            breaks: true,
            gfm: true,
            highlight: function(code, lang) {
                // 这里可以添加代码高亮逻辑,如果需要可以使用highlight.js
                return code;
            }
        });
         
        // 初始渲染
        updatePreview();
         
        // 监听输入变化
        markdownInput.addEventListener('input', updatePreview);
         
        // 更新预览函数
        function updatePreview() {
            const markdownText = markdownInput.value;
            previewContent.innerHTML = marked.parse(markdownText);
        }
         
        // 上传文件处理
        uploadBtn.addEventListener('click', function() {
            fileInput.click();
        });
         
        fileInput.addEventListener('change', function(e) {
            const file = e.target.files[0];
            if (!file) return;
             
            const reader = new FileReader();
            reader.onload = function(e) {
                markdownInput.value = e.target.result;
                updatePreview();
            };
            reader.readAsText(file);
        });
         
        // 下载HTML文件
        downloadBtn.addEventListener('click', function() {
            const markdownText = markdownInput.value;
            const htmlContent = marked.parse(markdownText);
             
            const htmlTemplate = `<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Markdown导出</title>
    <style>
        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
            line-height: 1.6;
            color: #333;
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
        }
         
        h1, h2, h3, h4, h5, h6 {
            margin-top: 24px;
            margin-bottom: 16px;
            font-weight: 600;
            line-height: 1.25;
        }
         
        h1 {
            padding-bottom: 0.3em;
            font-size: 2em;
            border-bottom: 1px solid #eaecef;
        }
         
        h2 {
            padding-bottom: 0.3em;
            font-size: 1.5em;
            border-bottom: 1px solid #eaecef;
        }
         
        p {
            margin-top: 0;
            margin-bottom: 16px;
        }
         
        a {
            color: #0366d6;
            text-decoration: none;
        }
         
        a:hover {
            text-decoration: underline;
        }
         
        code {
            font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace;
            padding: 0.2em 0.4em;
            margin: 0;
            font-size: 85%;
            background-color: rgba(27, 31, 35, 0.05);
            border-radius: 3px;
        }
         
        pre {
            background-color: #f6f8fa;
            border-radius: 3px;
            padding: 16px;
            overflow: auto;
            line-height: 1.45;
        }
         
        pre code {
            padding: 0;
            margin: 0;
            background-color: transparent;
            border-radius: 0;
        }
         
        blockquote {
            padding: 0 1em;
            color: #6a737d;
            border-left: 0.25em solid #dfe2e5;
            margin: 0 0 16px 0;
        }
         
        table {
            border-collapse: collapse;
            margin: 16px 0;
            width: 100%;
        }
         
        table th, table td {
            padding: 6px 13px;
            border: 1px solid #dfe2e5;
        }
         
        table tr {
            background-color: #fff;
            border-top: 1px solid #c6cbd1;
        }
         
        table tr:nth-child(2n) {
            background-color: #f6f8fa;
        }
         
        img {
            max-width: 100%;
        }
    </style>
</head>
<body>
${htmlContent}
</body>
</html>`;
             
            const blob = new Blob([htmlTemplate], { type: 'text/html' });
            const url = URL.createObjectURL(blob);
             
            const a = document.createElement('a');
            a.href = url;
            a.download = 'markdown-export.html';
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            URL.revokeObjectURL(url);
        });
    </script>
</body>
</html>