markdown 中启用音频支持

markdown 中启用音频支持

markdown 默认不支持音频文件,我们通过 html 标签渲染

flask项目

其中音频文件放在 /static/audios/vad_example.wav

markdown 内容如下:

复制代码
## 音频播放器示例
<audio controls  >
    <source src="vad_example.wav" type="audio/wav">
</audio>

预览显示为html

html 复制代码
<p>&lt;audio controls &gt;<br> &lt;source src="vad_example.wav" type="audio/wav"&gt;<br>&lt;/audio&gt;</p>

我们需要把上面代码变为如下html:

html 复制代码
<audio controls  >
    <source src="{{ url_for('static', filename='audios/vad_example.wav') }}" type="audio/wav">
</audio>

1编辑器预览区替换

markdown编辑器的html 代码:

html 复制代码
        <div id="create-editormd" class="editor">
            <textarea name="doc" id="doc">{{ request.form['doc'] or post['body'] if post else '' }}</textarea>
        </div>

js脚本:

预览区域默认html标签 editormd-preview

通过 onload 预览触发替换

js 复制代码
<script type="text/javascript">
    var testEditor;
    var textarea = document.getElementById('doc');

    $(function () {

        testEditor = editormd("create-editormd",
            {
                width: "90%",
                height: 640,
                syncScrolling: "single",
                path: "{{ url_for('static',filename='editormd/lib/') }}",
                imageUpload: true,
                imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp"],
                imageUploadURL: "/upload/upload_image",  // 设置图片上传的服务器路径
                onload: function () {
                    console.log("onload");
                    // 动态替换音频文件路径
                    const audioPathPrefix = "{{ url_for('static', filename='audios/') }}";
                    const previewContainer = document.querySelector('.editormd-preview');

                    if (previewContainer) {
                        console.log("Found preview container:", previewContainer);

                        // 查找并替换 <p> 标签内的音频标签
                        const pElements = previewContainer.querySelectorAll('p');
                        pElements.forEach(pElement => {
                            const htmlContent = pElement.innerHTML;

                            // 使用正则表达式匹配 <p> 标签内的音频标签
                            const audioRegex = /&lt;audio\s+controls[^&gt;]*&gt;[\s\S]*&lt;source\s+src="([^"]+)"\s+type="audio\/wav"[^&gt;]*&gt;[\s\S]*&lt;\/audio&gt;/g;
                            const matches = htmlContent.match(audioRegex);

                            if (matches) {
                                matches.forEach(match => {
                                    // 替换 &lt; 和 &gt; 为 < 和 >
                                    let actualHtml = match.replace(/&lt;/g, '<').replace(/&gt;/g, '>');

                                    // 移除 <br> 标签
                                    actualHtml = actualHtml.replace(/<br>/g, '');

                                    // 替换 <p> 标签内的内容
                                    pElement.innerHTML = pElement.innerHTML.replace(match, actualHtml);
                                    console.log("Replaced audio tag:", actualHtml);
                                });
                            }else{
                                console.log("No audio tags found in p element.");
                            }
                        });

                        // 更新音频文件路径
                        const audioElements = previewContainer.querySelectorAll('audio source');

                        if (audioElements.length > 0) {
                            console.log("Found audio elements:", audioElements);
                            audioElements.forEach(element => {
                                const originalSrc = element.getAttribute('src');
                                const newSrc = audioPathPrefix + originalSrc;
                                element.setAttribute('src', newSrc);
                                console.log("Updated src from", originalSrc, "to", newSrc);
                            });
                        } else {
                            console.log("No audio elements found.");
                        }
                    } else {
                        console.log("No preview container found.");
                    }
                }
            });
    });

</script>

显示页面 :

2 显示页面替换

html:

html 复制代码
    <!-- 预览区域 -->
    <div id="preview-wrapper" class="markdown-body">
        <!-- 这里会显示Markdown的渲染内容 -->
    </div>

js 脚本:

html 复制代码
<script type="text/javascript">

    document.addEventListener("DOMContentLoaded", function () {

        const preview = document.getElementById("preview-wrapper")

	// 更新预览
	preview.innerHTML = '';
	editormd.markdownToHTML(preview.id, {
		markdown: docBody,
		htmlDecode: "style,script,iframe",
		emoji: true,
		taskList: true,
		tex: true,
		flowChart: true,
		sequenceDiagram: true,
	});

	// 动态替换音频文件路径
	// 假设 audio_path 是从 Flask 传递过来的变量
	const audioPathPrefix = "{{ url_for('static', filename='audios/') }}";
	const audioElements = preview.querySelectorAll('audio source');
	audioElements.forEach(element => {
		const originalSrc = element.getAttribute('src');
		const newSrc = audioPathPrefix + originalSrc;
		element.setAttribute('src', newSrc);
	});

    });

</script>

显示页面 :

相关推荐
超皮小龙猫6 小时前
c语言-1
c语言·开发语言
fastjson_6 小时前
Edge浏览器开启IE兼容模式
javascript·edge·html
郝学胜-神的一滴7 小时前
完全二叉树与堆底层原理深度剖析 | 手写C++大顶堆实现
java·开发语言·数据结构·c++·python·算法
饼饼饼7 小时前
React19 新手指南:JSX 没那么难,用好这几条规则就够了
前端·javascript·react.js
黄毛火烧雪下7 小时前
Java 基础笔记:文件、递归与字符编码
java·开发语言·笔记
丷丩7 小时前
MapLibre GL JS第50课:用表达式创建虚线渐变线
javascript·gis·mapbox·maplibre gl js
swordbob8 小时前
CAP 定理:为什么不能同时实现 C、A、P?
开发语言·后端·spring
疯狂成瘾者8 小时前
Java 常用工具包 java.util
java·开发语言·windows
枫叶丹48 小时前
【HarmonyOS 6.0】MDM Kit 新特性:PC/2in1设备无锁屏密码重启自动解锁能力详解
开发语言·华为·harmonyos
ZHW_AI课题组8 小时前
Python 调用百度智能云 API 实现地址识别
开发语言·人工智能·python·机器学习·百度·数据挖掘