I'm trying to make a basic web application which converts markdown in a <textarea>
into HTML. For this I wanted to use the PageDown library, which SO also uses: https://code.google.com/archive/p/pagedown/wikis/PageDown.wiki.
I downloaded the PageDown source code, extracted it and placed it inside the top-level directory containing my HTML/JS files. So the directory structure looks like this:
.
├── 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
Then I tried to load it in the following way:
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>
Then I'm running the code in Chrome using the VSCode Live Server extension. I get the following output:
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
So I tried changing the path to the Markdown.*
scripts to /pagedown/Markdown.*.js
, and pagedown/Markdown.*.js
, but I got the same error for both.
I'm not really sure what I'm doing wrong here.
CodePudding user response:
1. Literal answer
You need to alter the import
path in your main.js
to the relative location of Markdown.Converter.js
:
import { Converter } from './pagedown/Markdown.Converter.js';
2. Module error
But if you try this now, you will get some error like:
Uncaught SyntaxError: The requested module './pagedown/Markdown.Converter.js' does not provide an export named 'Converter'
3. The fix
And this is because Markdown.Converter.js
is not an ESM JavaScript file. We can tell this because it has no export
statements.
3.1 ESM to non-ESM
What we have to appeal to instead is the "old-fashioned" version of loading the script, as these scripts are setting their library code into the "global" scope. We can see this in Markdown.Converter.js
since in the first few lines of it, it has this statement not wrapped in any other scope:
var Markdown;
So, to give these scripts access to the global scope such that main.js
can "access" their code, we need to remove the type="module"
from these scripts, since (as per MDN documentation):
Module-defined variables are scoped to the module unless explicitly attached to the global object.
So now your index.html
should be
<!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"></script>
<script src="./pagedown/Markdown.Converter.js"></script>
<script src="./pagedown/Markdown.Sanitizer.js"></script>
<script 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>
3.1.1 ESM script loading note
Note: as per the same MDN documentation mentioned above:
There is no need to use the
defer
attribute (see<script>
attributes) when loading a module script; modules are deferred automatically.
We don't need the defer
on the main.js
script.
3.2 Remove the import
Now Markdown
is in the global scope available to main.js
and we no longer need the import
statement so your entire main.js
should now look like:
var text = "**Markdown rocks**"
var converter = new Markdown.Converter();
var html = converter.makeHtml(text);