this.eleventy is not available in JavaScript template functions
j-f1 opened this issue · comments
Operating system
macOS Ventura 13.2 (22D49)
Eleventy
2.0.0-beta.3
Describe the bug
When creating a shortcode in any other template language, this.eleventy
is available as described in the docs. However, for a function added with addJavaScriptFunction
, the this
property does not have an eleventy
property.
Reproduction steps
- Clone https://gist.github.com/j-f1/8127173e227be4af465c1ad9063f95d0
- Run
npm install; npm run build
Expected behavior
_site/example/index.html
contains the useful content of this.eleventy
Actual behavior: the property is missing
Reproduction URL
https://gist.github.com/j-f1/8127173e227be4af465c1ad9063f95d0
Screenshots
No response
Switched my code to process.env.ELEVENTY_ROOT
and it works now. Feel free to close if you don’t want to change this behavior!
Hmm, gonna milestone this into 2.0.1 for now!
I have a probably related issue where this
isn’t available anymore when mapping through a collection.
this
is still available in the root of the createLegacyRedirects
method, but not anymore when slugify
is called and wrapJavascriptFunction
tries to assign page
to this
.
const paths = new Map([['text', 'notes']])
module.exports = class Redirects {
data() {
return {
layout: null,
permalink: '_redirects',
eleventyExcludeFromCollections: true,
}
}
createLegacyRedirects(collection, currentBase) {
const { slugify } = this
return collection
.map(function (item) {
const { permalink, external } = item.data
if (external) return ''
const cleanedPermalink = permalink.replace(`/${currentBase}/`, '')
const redirects = []
if (item.data.oldTitles) {
item.data.oldTitles.forEach(function (title) {
redirects.push(
`/${currentBase}/${slugify(title)}/ ${permalink} 301`,
)
})
}
if (paths.get(currentBase)) {
redirects.push(
`/${paths.get(currentBase)}/${cleanedPermalink} ${permalink} 301`,
)
}
return redirects.join('\n')
})
.join('\n')
}
render({ collections }) {
const { blog, notes, aroundTheWeb } = collections
return `
https://11ty.owlish.dev/* /:splat 301
https://reading.ovl.design/* https://www.ovl.design/around-the-web/ 301
/atw /around-the-web/ 301
${this.createLegacyRedirects(blog, 'text')}
${this.createLegacyRedirects(notes, 'notes')}
`.trim()
}
}
That’s not related to Eleventy, it’s the way JS works. If you use arrow functions for map
and forEach
you’ll still be able to access the this
value as expected.
Sorry, but I know «the way JS works». Those were arrow functions and it worked in v1 and broke after updating to v2. I just forgot to change it back before commenting.
For context, debugger screenshots. this
is undefined
in those functions no matter how I write them, and consequentially it’s undefined
in wrapJavaScriptFunction
.
I tried to bind this in the class constructor with this.createLegacyRedirects = this.createLegacyRedirects.bind(this)
but that didn’t solve the problem.
[11ty] Problem writing Eleventy templates: (more in DEBUG output)
[11ty] 1. Having trouble rendering 11ty.js template ./_src/_redirects.11ty.js (via TemplateContentRenderError)
[11ty] 2. Cannot set properties of undefined (setting 'page') (via TypeError)
[11ty]
[11ty] Original error stack trace: TypeError: Cannot set properties of undefined (setting 'page')
[11ty] at /Users/owl/dev/ovl/www.ovl.design/node_modules/@11ty/eleventy/src/Engines/JavaScript.js:113:19
[11ty] at /Users/owl/dev/ovl/www.ovl.design/_src/_redirects.11ty.js:37:34
[11ty] at Array.forEach (<anonymous>)
[11ty] at /Users/owl/dev/ovl/www.ovl.design/_src/_redirects.11ty.js:35:31
[11ty] at Array.map (<anonymous>)
[11ty] at Redirects.createLegacyRedirects (/Users/owl/dev/ovl/www.ovl.design/_src/_redirects.11ty.js:25:8)
[11ty] at Redirects.render (/Users/owl/dev/ovl/www.ovl.design/_src/_redirects.11ty.js:60:8)
[11ty] at JavaScript.<anonymous> (/Users/owl/dev/ovl/www.ovl.design/node_modules/@11ty/eleventy/src/Engines/JavaScript.js:144:43)
Appreciate any useful tips.
I see — that looks like a different issue where wrapJavaScriptFunction
expects the this
value to be a valid object but calling the function as-is (e.g. by doing const { slugify } = this; slugify()
) gives it a this
of undefined
.
But I can't do this.slugify
as this is already undefined in the nested functions. Maybe binding this to slugify outside of the loops can be a workaround, even if it doesn't explain why it breaks after updating.
disregard this comment I had some reading comprehension problems 🫠
Shipping witih 2.0.1—thank you!