markdown 中启用音频支持

markdown 中启用音频支持

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

flask项目

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

markdown 内容如下:

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

预览显示为html

<p>&lt;audio controls &gt;<br> &lt;source src="vad_example.wav" type="audio/wav"&gt;<br>&lt;/audio&gt;</p>

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

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

1编辑器预览区替换

markdown编辑器的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 预览触发替换

<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:

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

js 脚本:

<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>

显示页面 :
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/55790.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Flink源码剖析

写在前面 最近一段时间都没有更新博客了&#xff0c;原因有点离谱&#xff0c;在实现flink的两阶段提交的时候&#xff0c;每次执行自定义的notifyCheckpointComplete时候&#xff0c;好像就会停止消费数据&#xff0c;完成notifyComplete后再消费数据&#xff1b;基于上述原因…

go-zero学习

go-zero官网&#xff1a; https://go-zero.dev/docs/tasks 好文&#xff1a; https://blog.csdn.net/m0_63629756/article/details/136599547 视频&#xff1a; https://www.bilibili.com/video/BV18JxUeyECg 微服务基础 根目录下&#xff0c;一个文件夹就是一个微服务。如果微…

力扣16~20题

题16&#xff08;中等&#xff09;&#xff1a; 思路&#xff1a; 双指针法&#xff0c;和15题差不多&#xff0c;就是要排除了&#xff0c;如果total<target则排除了更小的&#xff08;left右移&#xff09;&#xff0c;如果total>target则排除了更大的&#xff08;rig…

kafka的成神秘籍(java)

kafka的成神秘籍 kafka的简介 ​ Kafka 最初是由Linkedin 即领英公司基于Scala和 Java语言开发的分布式消息发布-订阅系统&#xff0c;现已捐献给Apache软件基金会。Kafka 最被广为人知的是作为一个 消息队列(mq)系统存在&#xff0c;而事实上kafka已然成为一个流行的分布式流…

【mmengine】配置器(config)(进阶)继承与导出,命令行修改配置

一、配置文件的继承 1.1 继承机制概述 新建optimizer_cfg.py: optimizer dict(typeSGD, lr0.02, momentum0.9, weight_decay0.0001)新建runtime_cfg.py: device "cuda" gpu_ids [0, 1] batch_size 64 epochs 100 num_workers 8新建resnet50.py: _base_ […

PostgreSQL 小课专栏大纲

PostgreSQL 介绍及发展历史 介绍 发展历史 克隆 PostgreSQL 的源代码 找到其第一次提交记录 看下第一次提交的信息 发布策略、版本号及生命周期 探索 PostgreSQL 中的术语 总结 PostgreSQL 安装 编译方式安装 yum 方式安装 apt 方式安装 Docker 方式运行 Mac/Win…

Observer(观察者模式)

1. 意图 定义对象间的一种一对多的依赖关系&#xff0c;当一个对象的状态发生改变时&#xff0c;所有依赖于它的对象都得到通知并被自动更新。 在观察者模式中&#xff0c;有两类对象&#xff1a;被观察者&#xff08;Subject&#xff09;和观察者&#xff08;Observer&#xf…

单片机原理与技术

文章目录 一、单片机概述二、单片机的基本原理1. **硬件结构**2. **指令系统** 三、单片机的关键技术1. **编程技术**2. **接口技术**3. **嵌入式系统技术** 四、单片机在现代科技中的应用 一、单片机概述 单片机&#xff0c;全称为单片微型计算机&#xff08;Single-Chip Mic…

Vue 路由设置

为了防止遗忘&#xff0c;记录一下用Vue写前端配置路由时的过程&#xff0c;方便后续再需要用到时回忆。 一、举个例子 假如需要实现这样的界面逻辑&#xff1a; 在HomePage中有一组选项卡按钮用于导航到子页面&#xff0c;而子页面Page1中有一个按钮&#xff0c;其响应事件是…

笔记-stm32移植ucos

文章目录 一、UCOS的基础知识1.1 前后台系统:1.2 RTOS系统可剥夺型内核:前后台系统和RTOS系统 1.3 UCOS系统简介学习方法 二、ucossii移植Step1&#xff1a;在工程中建立存放UCOSS代码的文件夹UCOSIIStep2:向CORE文件夹添加文件Step3:向Config文件夹添加文件Step4:向port文件夹…

LLM4Rec最新工作: 字节发布用于序列推荐的分层大模型HLLM

前几个月 Meta HSTU 点燃各大厂商对 LLM4Rec 的热情&#xff0c;一时间&#xff0c;探索推荐领域的 Scaling Law、实现推荐的 ChatGPT 时刻、取代传统推荐模型等一系列话题让人兴奋&#xff0c;然而理想有多丰满&#xff0c;现实就有多骨感&#xff0c;尚未有业界公开真正复刻 …

后端复习资料

后端面试资料 语雀-图灵面试题 语雀-javaGuide 小林coding&#xff1a;https://www.xiaolincoding.com/ 面试鸭&#xff1a; https://www.mianshiya.com/ codehot香菜哥&#xff1a;https://codehot.cn/markdown/welfare 面试题&#xff1a; vizard自行整理 牛客Golang社招面…

vscode中配置python虚拟环境

python虚拟环境作用 Python虚拟环境允许你为每个独立的项目创建一个隔离的环境&#xff0c;这样每个项目都可以拥有自己的一套Python安装包和依赖&#xff0c;不会互相影响。实际使用中&#xff0c;可以在vscode或pycharm中使用虚拟环境。 1.创建虚拟环境的方法&#xff1a; …

【NLP自然语言处理】01-基础学习路径简介

目的&#xff1a;让大家能够在 AI-NLP 领域由基础到入门具体安排&#xff1a; NLP介绍 文本预处理RNN 及其变体&#xff08;涉及案例&#xff09;Transformer 原理详解迁移学习 和 Bert 模型详解 &#xff08;涉及案例&#xff09;特点&#xff1a; 原理 实践每个文章会有练习…

04-SpringBootWeb案例(中)

3. 员工管理 完成了部门管理的功能开发之后&#xff0c;我们进入到下一环节员工管理功能的开发。 基于以上原型&#xff0c;我们可以把员工管理功能分为&#xff1a; 分页查询&#xff08;今天完成&#xff09;带条件的分页查询&#xff08;今天完成&#xff09;删除员工&am…

算法题总结(十)——二叉树上

#二叉树的递归遍历 // 前序遍历递归LC144_二叉树的前序遍历 class Solution {public List<Integer> preorderTraversal(TreeNode root) {List<Integer> result new ArrayList<Integer>(); //也可以把result 作为全局变量&#xff0c;只需要一个函数即可。…

Linus Torvalds 要求内核开发人员编写更好的 Git 合并提交信息

昨天在宣布 Linux 6.12-rc2 内核时&#xff0c;Linus Torvalds 要求内核维护者在提交信息方面做得更好。Torvalds 尤其希望内核维护者在描述拉取请求中的变更时&#xff0c;能更好地使用积极、命令式的语气。 Linux创建者在6.12-rc2 公告中解释道&#xff1a; 总之&#xff0c…

论文阅读笔记-XLNet: Generalized Autoregressive Pretraining for Language Understanding

前言 Google发布的XLNet在问答、文本分类、自然语言理解等任务上都大幅超越BERT,XLNet提出一个框架来连接语言建模方法和预训练方法。我们所熟悉的BERT是denoising autoencoding模型,最大的亮点就是能够获取上下文相关的双向特征表示,所以相对于标准语言模型(自回归)的预…

数据结构-基于不同策略的英文单词的词频统计和检索系统

数据结构课程设计:基于不同策略的英文单词的词频统计和检索系统 - 海月CSDN - 博客园 数据结构-基于不同策略的英文单词的词频统计和检索系统-CSDN博客 李冬梅老师课程设计 多学多练习!!!! C/C++在线餐馆预订管理系统_数据结构美团餐馆预订管理信息系统-CSDN博客 高校…

Java之Native详解

在Java编程中&#xff0c;Native方法是一种特殊的方法&#xff0c;它允许Java代码直接调用用其他编程语言&#xff08;如C或C&#xff09;编写的代码。这种机制使得Java程序能够与底层系统资源或其他编程语言进行交互&#xff0c;实现更高效的操作或访问特定功能。本文将详细介…