无法将PageDown JS库导入Web应用,求解决方法
我正在开发一个基础Web应用,用来把<textarea>里的Markdown转换成HTML,打算用Stack Overflow同款的PageDown库。已经把PageDown源码解压到HTML/JS文件所在的顶层目录,目录结构如下:
. ├── index.html ├── main.js ├── pagedown │ ├── LICENSE.txt │ ├── Markdown.Converter.js │ ├── Markdown.Editor.js │ ├── Markdown.Sanitizer.js │ ├── README.txt │ ├── demo │ ├── local │ ├── node-pagedown.js │ ├── package.json │ ├── resources │ └── wmd-buttons.png └── style.css
尝试按以下方式加载库:
main.js代码:
import { Converter } from 'Markdown.Converter.js' var text = "**Markdown rocks**" var converter = new Markdown.Converter(); var html = converter.makeHtml(text);
index.html代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="style.css"> <script type="module" src="main.js" defer></script> <script type="module" src="./pagedown/Markdown.Converter.js"></script> <script type="module" src="./pagedown/Markdown.Sanitizer.js"></script> <script type="module" src="./pagedown/Markdown.Editor.js"></script> <title>Text</title> </head> <body> <textarea name="" id="textinput" cols="30" rows="10"></textarea> <div id="output"></div> </body> </html>
用VSCode Live Server在Chrome中运行后,出现以下错误:
Uncaught TypeError: Failed to resolve module specifier "Markdown.Converter.js". Relative references must start with either "/", "./", or "../". Markdown.Sanitizer.js:8 Uncaught TypeError: Cannot read properties of undefined (reading 'Converter') at Markdown.Sanitizer.js:8:28 at Markdown.Sanitizer.js:108:3 (anonymous) @ Markdown.Sanitizer.js:8 (anonymous) @ Markdown.Sanitizer.js:108 Markdown.Editor.js:92 Uncaught ReferenceError: Markdown is not defined at Markdown.Editor.js:92:5 at Markdown.Editor.js:2301:3
试过修改Markdown.*脚本的路径为/pagedown/Markdown.*.js和pagedown/Markdown.*.js,错误依然存在,不知道问题出在哪。
核心问题:PageDown不是ES模块
PageDown的原始脚本是基于全局变量的传统JS文件,并非为ES模块设计。直接用type="module"加载会导致依赖关系断裂——Sanitizer和Editor都依赖全局的Markdown对象,但模块作用域会隔离这个变量,导致后续脚本找不到它。
具体修复步骤:
移除所有
type="module"属性
在index.html中,把所有<script>标签的type="module"去掉,让脚本在全局作用域执行,确保三个PageDown脚本能正确共享Markdown对象。同时调整脚本顺序,把PageDown的文件放在main.js前面:<link rel="stylesheet" href="style.css"> <script src="./pagedown/Markdown.Converter.js"></script> <script src="./pagedown/Markdown.Sanitizer.js"></script> <script src="./pagedown/Markdown.Editor.js"></script> <script src="main.js" defer></script>修改main.js的代码
不再需要ES模块的导入语句,直接使用全局的Markdown对象即可。还可以添加代码把转换后的HTML渲染到页面:var text = "**Markdown rocks**" var converter = new Markdown.Converter(); var html = converter.makeHtml(text); // 把结果输出到页面的output容器 document.getElementById('output').innerHTML = html;(可选)添加编辑器样式
如果要使用PageDown的可视化编辑器,需要从pagedown/demo/wmd.css复制样式文件到项目中,然后在index.html引入:<link rel="stylesheet" href="wmd.css">
为什么之前的路径修改没用?
修改路径只是解决了模块路径解析的第一个错误,但PageDown本身不支持ES模块,Sanitizer和Editor依然找不到全局的Markdown对象——模块作用域里的变量不会自动挂载到全局。只有让所有脚本在全局作用域运行,才能保证三个PageDown脚本之间的依赖关系正常工作。
内容的提问来源于stack exchange,提问作者Lou

