PostHTML Plugins: ast.walk is not a function
See original GitHub issue🐛 bug report
I was using Parcel, PostHTML and several PostHTML plugins to create my documents. However the build fails on certain conditions.
🎛 Configuration (.babelrc, package.json, cli command)
Here is my .posthtmlrc
:
{
"plugins": {
"posthtml-include-md": true,
}
}
test.html
(plugins above do not have any effect on this HTML since this doesn’t include any markdown paragraphs):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div class="baz">foobar</div>
</body>
</html>
CLI Command: $ parcel test.html
🤔 Expected Behavior
$ parcel test.html
Server running at http://localhost:1234
✨ Built in 6ms.
😯 Current Behavior
$ parcel test.html
Server running at http://localhost:1234
🚨 /path/to/my/document/test.html: ast.walk is not a function
at HTMLAsset.collectDependencies (/path/to/parcel/packages/core/parcel-bundler/src/assets/HTMLAsset.js:138:9)
at HTMLAsset.getDependencies (/path/to/parcel/packages/core/parcel-bundler/src/Asset.js:81:18)
💁 Possible Solution
Following the stack trace and the source code, I figured out that the problem came from where Parcel loaded plugins. ast
in the error log above was not an object that expresses AST but was a expoted function that returns an actual plugin function (that takes a tree as an argument). As PostHTML process()
function didn’t have type checks, it simply returned an actual plugin function which clearly didn’t have a walk
property.
I made a small modification to /packages/core/parcel-bundler/src/utils/loadPlugins.js
then the build succeeded. I removed a length check for options
so that plugin
functions were always executed even with empty options
.
async function loadPlugin(plugin, relative, options) {
...
if (typeof options !== 'object') {
options = {};
}
if (Object.keys(options).length > 0) { // removed this
plugin = plugin(options);
}
...
Giving the plugin options (like {"a":"b"}
instead of true
) in .posthtmlrc
also made the build successful.
In addition, README.md of posthtml/posthtml also shows that we have to call the exported functions (require('...')()
) of the plugin before calling process(ast, options)
since they are functions that return functions.
posthtml(
[
require('posthtml-to-svg-tags')(),
require('posthtml-extend-attrs')({
attrsTree: {
'.wow' : {
id: 'wow_id',
fill: '#4A83B4',
'fill-rule': 'evenodd',
'font-family': 'Verdana'
}
}
})
])
.process(html/*, options */)
.then((result) => console.log(result.html))
As the changes I made to loadPlugins.js
might cause problems of other transformers such as PostCSS, I tried to modifying parcel-bundler/src/transforms/posthtml.js
instead but I wasn’t able to figure out how to pass the plugins’ options to them. For Parcel v2 this should be straightforward thanks to the non-shared loadPlugins.js
.
🔦 Context
💻 Code Sample
🌍 Your Environment
Software | Version(s) |
---|---|
Parcel | 1.12.3 |
Node | v11.13.0 |
npm/Yarn | 1.16.0 (yarn) |
Operating System | Arch Linux (kernel: 5.0.5-arch1-1) |
Issue Analytics
- State:
- Created 4 years ago
- Comments:5 (2 by maintainers)
Using this configuration seems to work (without any modifications to parcel itself):
But
true
should still work…Same problem here… specifying
{}
fixed the problem.