Skip to content

Commit f6de1f0

Browse files
committed
fix(eleventy): make eleventy engine more lenient for dynamic components
Updates the `@bookshop/eleventy-engine` plugin to allow the use of: `{% bookshop {{_bookshop_name}} %}`, where currently it only works with: `{% bookshop "{{_bookshop_name}}" %}` (quoted). The former seems to work in Eleventy in some cases, so the live rendering should be lenient on its input here.
1 parent e40800f commit f6de1f0

File tree

3 files changed

+60
-24
lines changed

3 files changed

+60
-24
lines changed

javascript-modules/engines/eleventy-engine/lib/translateLiquid.js

+31-14
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,30 @@
11
import { Tokenizer } from 'liquidjs';
22

3-
const rewriteTag = function(token, src, liveMarkup) {
3+
// Put quotes around rewritten dynamic values.
4+
// Assuming that if this code is running, the Eleventy build succeeded.
5+
// A _bookshop_{{val}} include without quotes __will__ break in liquidjs,
6+
// but seems to work in Eleventy?
7+
const quoteDynamicNames = (raw) => {
8+
return raw.replace(
9+
/\s_bookshop_(include_)?{{(.+)}}\s/,
10+
(_, include, innards) => {
11+
return ` "_bookshop_${include || ''}{{${innards}}}" `
12+
}
13+
);
14+
}
15+
16+
const rewriteTag = function (token, src, liveMarkup) {
417
let raw = token.getText();
518

619
// Skip html and {% end... %} tags
720
if (token.kind === 16) return src; // html
821
if (token.name && token.name.match(/^end/)) return src;
922

10-
if (liveMarkup && token.name && token.name === 'for'){
23+
if (liveMarkup && token.name && token.name === 'for') {
1124
raw = `${raw}{% loop_context ${token.args} %}`
1225
}
1326

14-
if (liveMarkup && token.name && (token.name === 'assign' || token.name === 'local')){
27+
if (liveMarkup && token.name && (token.name === 'assign' || token.name === 'local')) {
1528
let identifier = token.args.split('=').shift().trim();
1629
raw = `${raw}<!--bookshop-live context(${identifier}="{{${identifier}}}")-->`
1730
}
@@ -21,12 +34,14 @@ const rewriteTag = function(token, src, liveMarkup) {
2134
let componentName;
2235
token.name = 'include';
2336
raw = raw.replace(
24-
/bookshop_include ('|")?(\S+)/,
25-
(_, quote, component) => {
26-
componentName = component.replace(/('|")$/, '');
27-
return `include ${quote||''}_bookshop_include_${component}`
28-
}
37+
/bookshop_include ('|")?(\S+)/,
38+
(_, quote, component) => {
39+
componentName = component.replace(/('|")$/, '');
40+
return `include ${quote || ''}_bookshop_include_${component}`
41+
}
2942
);
43+
raw = quoteDynamicNames(raw);
44+
3045
if (liveMarkup) {
3146
let params = token.args.split(' ');
3247
params.shift();
@@ -39,12 +54,14 @@ const rewriteTag = function(token, src, liveMarkup) {
3954
let componentName;
4055
token.name = 'include';
4156
raw = raw.replace(
42-
/bookshop ('|")?(\S+)/,
43-
(_, quote, component) => {
44-
componentName = component.replace(/('|")$/, '');
45-
return `include ${quote||''}_bookshop_${component}`
46-
}
57+
/bookshop ('|")?(\S+)/,
58+
(_, quote, component) => {
59+
componentName = component.replace(/('|")$/, '');
60+
return `include ${quote || ''}_bookshop_${component}`
61+
}
4762
);
63+
raw = quoteDynamicNames(raw);
64+
4865
if (liveMarkup) {
4966
let params = token.args.split(' ');
5067
params.shift();
@@ -59,7 +76,7 @@ const rewriteTag = function(token, src, liveMarkup) {
5976
].join('');
6077
}
6178

62-
export default function(text, opts) {
79+
export default function (text, opts) {
6380
opts = {
6481
expandBindSyntax: true,
6582
liveMarkup: true,

javascript-modules/engines/eleventy-engine/lib/translateLiquid.test.js

+28-9
Original file line numberDiff line numberDiff line change
@@ -10,52 +10,71 @@ test("add unbind tag", t => {
1010
test("rewrite unquoted bookshop tags", t => {
1111
const input = `{% bookshop component prop: page.item %}`;
1212
const expected = `{% include _bookshop_component prop: page.item %}`;
13-
t.is(translateLiquid(input, {expandBindSyntax: false, liveMarkup: false}), expected);
13+
t.is(translateLiquid(input, { expandBindSyntax: false, liveMarkup: false }), expected);
1414
});
1515

1616
test("rewrite bookshop tags", t => {
1717
const input = `{% bookshop "component" prop: page.item %}`;
1818
const expected = `{% include "_bookshop_component" prop: page.item %}`;
19-
t.is(translateLiquid(input, {expandBindSyntax: false, liveMarkup: false}), expected);
19+
t.is(translateLiquid(input, { expandBindSyntax: false, liveMarkup: false }), expected);
2020
});
2121

22+
test("rewrite dynamic bookshop tags", t => {
23+
const input = `{% bookshop "{{ _bookshop_name }}" prop: page.item %}`;
24+
const expected = `{% include "_bookshop_{{ _bookshop_name }}" prop: page.item %}`;
25+
t.is(translateLiquid(input, { expandBindSyntax: false, liveMarkup: false }), expected);
26+
});
27+
28+
test("rewrite unquoted dynamic bookshop tags", t => {
29+
const input = `{% bookshop {{ _bookshop_name }} prop: page.item %}`;
30+
const expected = `{% include "_bookshop_{{ _bookshop_name }}" prop: page.item %}`;
31+
t.is(translateLiquid(input, { expandBindSyntax: false, liveMarkup: false }), expected);
32+
});
33+
34+
test("rewrite unquoted dynamic bookshop include tags", t => {
35+
const input = `{% bookshop_include {{ _bookshop_name }} prop: page.item %}`;
36+
const expected = `{% include "_bookshop_include_{{ _bookshop_name }}" prop: page.item %}`;
37+
t.is(translateLiquid(input, { expandBindSyntax: false, liveMarkup: false }), expected);
38+
});
39+
40+
2241
test("rewrite bookshop_include tags", t => {
2342
const input = `{% bookshop_include "helper" prop: page.item %}`;
2443
const expected = `{% include "_bookshop_include_helper" prop: page.item %}`;
25-
t.is(translateLiquid(input, {expandBindSyntax: false, liveMarkup: false}), expected);
44+
t.is(translateLiquid(input, { expandBindSyntax: false, liveMarkup: false }), expected);
2645
});
2746

2847
test("ignore the rest", t => {
2948
const input = `<div><h1>{{ title | default: "Hello World" }}</h1></div>`;
30-
t.is(translateLiquid(input, {expandBindSyntax: false, liveMarkup: false}), input);
49+
t.is(translateLiquid(input, { expandBindSyntax: false, liveMarkup: false }), input);
3150
});
3251

3352
test("add live markup to bookshop tags", t => {
3453
const input = `{% bookshop "component" prop: page.item %}`;
3554
const expected = `<!--bookshop-live name(component) params(prop: page.item)-->{% include "_bookshop_component" prop: page.item %}<!--bookshop-live end-->`;
36-
t.is(translateLiquid(input, {expandBindSyntax: false}), expected);
55+
t.is(translateLiquid(input, { expandBindSyntax: false }), expected);
3756
});
3857

3958
test("add live markup to bookshop_include tags", t => {
4059
const input = `{% bookshop_include "helper" prop: page.item %}`;
4160
const expected = `<!--bookshop-live name(helper) params(prop: page.item)-->{% include "_bookshop_include_helper" prop: page.item %}<!--bookshop-live end-->`;
42-
t.is(translateLiquid(input, {expandBindSyntax: false}), expected);
61+
t.is(translateLiquid(input, { expandBindSyntax: false }), expected);
4362
});
4463

4564
test("add live markup to assigns", t => {
4665
const input = `{% assign a=b %}`;
4766
const expected = `{% assign a=b %}<!--bookshop-live context(a="{{a}}")-->`;
48-
t.is(translateLiquid(input, {expandBindSyntax: false}), expected);
67+
t.is(translateLiquid(input, { expandBindSyntax: false }), expected);
4968
});
5069

5170
test("add live markup to local assigns", t => {
5271
const input = `{% local a=b %}`;
5372
const expected = `{% local a=b %}<!--bookshop-live context(a="{{a}}")-->`;
54-
t.is(translateLiquid(input, {expandBindSyntax: false}), expected);
73+
t.is(translateLiquid(input, { expandBindSyntax: false }), expected);
5574
});
5675

5776
test("add live markup to loops", t => {
5877
const input = `{% for a in b %}`;
5978
const expected = `{% for a in b %}{% loop_context a in b %}`;
60-
t.is(translateLiquid(input, {expandBindSyntax: false}), expected);
79+
t.is(translateLiquid(input, { expandBindSyntax: false }), expected);
6180
});

javascript-modules/live/lib/app/live.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const eleventyFiles = {
2323
[eleventyComponent('title-loop')]: "{% for t in titles %}{% bookshop 'title' title: t %}{% endfor %}",
2424
[eleventyComponent('num-loop')]: "{% for t in (min..max) %}{% bookshop 'title' title: t %}{% endfor %}",
2525
[eleventyComponent('wrapper')]: "{% bookshop '{{component}}' bind: page %}",
26-
[eleventyComponent('dynamic-loop')]: "{% for props in t %}{% bookshop '{{props._bookshop_name}}' bind: props %}{% endfor %}",
26+
[eleventyComponent('dynamic-loop')]: "{% for props in t %}{% bookshop {{props._bookshop_name}} bind: props %}{% endfor %}",
2727
}
2828

2929
const initial = async (liveInstance, component, props) => {

0 commit comments

Comments
 (0)