From 5126f0f66952bf260d1e5d5e0d8fdbd1ae19e556 Mon Sep 17 00:00:00 2001 From: Andrew Seier Date: Sun, 9 Mar 2025 14:49:22 -0700 Subject: [PATCH] =?UTF-8?q?Pass=20standard=20=E2=80=9CArray.map=E2=80=9D?= =?UTF-8?q?=20arguments=20to=20=E2=80=9Crepeat=E2=80=9D.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The “repeat” directive is just a shim to create arrays of _entries_. We may remove this from the interface in the future, but we do need it to function as expected in the interim! Most callers rely on just the first “value” argument, but there’s no good reason not to expose the `(value, index, array)`-triple that a standard callback would receive from “Array.map”. --- test/test-template-engine.js | 32 ++++++++++++++++++++++++++++++++ x-template.js | 4 ++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/test/test-template-engine.js b/test/test-template-engine.js index f9b1f48..0eecdb8 100644 --- a/test/test-template-engine.js +++ b/test/test-template-engine.js @@ -1241,6 +1241,38 @@ describe('html updaters', () => { assert(container.querySelector('#c').textContent === 'fuzz'); container.remove(); }); + + it('repeat callbacks are provided args from underlying “.map” call', () => { + // The identify callback is written in a bizarre way to test that all the + // expected function arguments are actually passed in. If they weren’t you + // would get duplicated key errors or undefined key errors. + const getTemplate = ({ items }) => { + return html` +
+ ${repeat(items, (_, index, array) => array?.[index]?.id, (_, index, array) => { + return html`
${array?.[index]?.id}
`; + })} +
+ `; + }; + const container = document.createElement('div'); + document.body.append(container); + render(container, getTemplate({ items: [{ id: 'foo' }, { id: 'bar'}, { id: 'baz' }] })); + const foo = container.querySelector('#foo'); + const bar = container.querySelector('#bar'); + const baz = container.querySelector('#baz'); + assert(container.querySelector('#target').childElementCount === 3); + assert(!!foo); + assert(!!bar); + assert(!!baz); + assert(container.querySelector('#target').children[0] === foo); + assert(container.querySelector('#target').children[1] === bar); + assert(container.querySelector('#target').children[2] === baz); + assert(foo.textContent === 'foo'); + assert(bar.textContent === 'bar'); + assert(baz.textContent === 'baz'); + container.remove(); + }); }); describe('updater errors', () => { diff --git a/x-template.js b/x-template.js index 91c1ba4..be0264a 100644 --- a/x-template.js +++ b/x-template.js @@ -126,8 +126,8 @@ class TemplateEngine { throw new Error(`Unexpected repeat callback "${callback}" provided, expected a function.`); } return identify - ? items.map(item => [identify(item), callback(item)]) - : items.map(item => callback(item)); // Just a basic array. + ? items.map((...args) => [identify(...args), callback(...args)]) + : items.map((...args) => callback(...args)); // Just a basic array. } // Deprecated. Will remove in future release.