eleventy-plugin-toc icon indicating copy to clipboard operation
eleventy-plugin-toc copied to clipboard

`TemplateContentRenderError` was thrown > cheerio.load() expects a string

Open mariusa opened this issue 4 years ago • 5 comments

Hi, getting this error

`TemplateContentRenderError` was thrown
> cheerio.load() expects a string, file:./modules.md, line:9

`RenderError` was thrown
> cheerio.load() expects a string

`Error` was thrown:
    Error: cheerio.load() expects a string
        at Function.exports.load (/usr/local/lib/node_modules/eleventy-plugin-toc/node_modules/cheerio/lib/static.js:30:11)
        at BuildTOC (/usr/local/lib/node_modules/eleventy-plugin-toc/src/BuildTOC.js:18:21)
        at /usr/local/lib/node_modules/eleventy-plugin-toc/.eleventy.js:8:14

with a simple .md file

        <h2>{{ page.title }}</h2>
        <div class="line-shape"></div>

{{ content | toc : '{"tags":["h2","h3"],"wrapper":"div","wrapperClass":"content-tableau"}' }}

mariusa avatar Jan 02 '21 10:01 mariusa

I found out that this happens when you try to use content on a content template itself. I guess you have to use this outside the content, e.g. on the layout template.

netmikey avatar Feb 16 '21 20:02 netmikey

Hm, that means maintaining a separate almost duplicate layout only for the page(s) which need a TOC. I come from jekyll, where one can say in a markdown content page 'insert a TOC here', which makes sense. TOC could be after some page content, not necessarily at the beginning.

mariusa avatar Feb 16 '21 21:02 mariusa

You could use a custom flag on pages you want / don't want a TOC and read that flag in your layout? Something along those lines:

{% if page.includeToc %}
  <aside>
    {{ content | toc }}
  </aside>
{% endif %}

I myself would prefer having the TOC at a predefined position within the article (after the h1 and the abstract, before the first h2), pretty much like you explained. But that doesn't seem feasible from within the layout...?

(oh, and #22 is also a blocker for me)

netmikey avatar Feb 16 '21 21:02 netmikey

Thanks for creating this issue.

First, the troubleshooting you all have done is correct: because this plugin provides a filter on content, it can only be used where Eleventy has the content variable available (like a layout template). Within a content file itself, content is undefined (it's not an object we can get a string from, as one comment suggested). Additionally, eleventyComputed doesn't have access to processed content in an .11tydata.js file.

Second, could you help me understand how using a layout template is a drawback here? As I approach this problem, that seems to be the right solution: since content doesn't exist until a content file has been processed, it's necessary to have a layout template if you need to use content.

@mariusa - do you have a link to Jekyll documentation/source for its TOC generation/insertion? I'll take a look at that to see if anything's comparable with Eleventy's processing pipeline.

jdsteinbach avatar Sep 28 '21 18:09 jdsteinbach

could you help me understand how using a layout template is a drawback here?

Example: a site with regular HTML pages, but also some .md pages (FAQ). Both use the same layout, which has header & footer.

FAQ page:

---
title: FAQ
---

Our APIs provide access to ...

<h4>Table of Contents</h4>
  * this unordered seed list will be replaced by toc as unordered list
  {:toc}

# Overview

## First topic here
...

This works with Jekyll. Good things:

  1. No need for an extra layout
  2. I can add custom page text/content before TOC for every page, all pages using the same layout

Jekyll how-to (no plugins required, using kramdown) https://stackoverflow.com/questions/38417624/table-of-contents-using-jekyll-and-kramdown

mariusa avatar Oct 01 '21 07:10 mariusa