Parcel: PostHTML Plugins: ast.walk is not a function

Created on 23 Jun 2019  ยท  5Comments  ยท  Source: parcel-bundler/parcel

๐Ÿ› 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:

```.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):
```html
<!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) |

Bug HTML Preprocessing

Most helpful comment

Using this configuration seems to work (without any modifications to parcel itself):

{
  "plugins": {
    "posthtml-include-md": {},
  }
}

But true should still work...

All 5 comments

Using this configuration seems to work (without any modifications to parcel itself):

{
  "plugins": {
    "posthtml-include-md": {},
  }
}

But true should still work...

Specifying {} as a value has worked.
I tried parcel packages instead of parcel-bundler but using true still throws the same error.

I tried parcel packages instead of parcel-bundler but using true still throws the same error.

As of now, parcel and parcel-bundler are identical.

I installed parcel on another machine I own and it worked. I still don't get why it didn't work on my main laptop, but anyway, I'm gonna close the issue since the reproduction seems difficult. Thanks.

  "devDependencies": {
    "parcel-bundler": "^1.12.4",
    "posthtml-include": "^1.4.3"
{
  "plugins": {
    "posthtml-include": true
  }
}

Same problem here.... specifying {} fixed the problem.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dotdash picture dotdash  ยท  3Comments

termhn picture termhn  ยท  3Comments

oliger picture oliger  ยท  3Comments

will-stone picture will-stone  ยท  3Comments

dsky1990 picture dsky1990  ยท  3Comments