Skip to content

Commit 31fbaa3

Browse files
committed
Fixes #152
1 parent 66bee0e commit 31fbaa3

File tree

5 files changed

+51
-12
lines changed

5 files changed

+51
-12
lines changed

src/ast.js

+29-10
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,20 @@ class AstSerializer {
405405
return str;
406406
}
407407

408+
// This will be the parent component in component definition files, and the host component in slotted content
409+
getAncestorComponentForData(options) {
410+
// slot content is content in the host component, not in the component definition.
411+
// https://github.com/11ty/webc/issues/152
412+
if(options.isSlottedContent) {
413+
return this.componentManager.get(options.hostComponentContextFilePath);
414+
}
415+
return this.componentManager.get(options.closestParentComponent);
416+
}
417+
418+
useGlobalDataAtTopLevel(ancestorComponent) {
419+
return ancestorComponent?.isTopLevelComponent ?? true;
420+
}
421+
408422
async renderStartTag(node, tagName, component, renderingMode, options) {
409423
let content = "";
410424

@@ -430,7 +444,9 @@ class AstSerializer {
430444
}
431445
}
432446

433-
let nodeData = this.dataCascade.getData( parentComponent.isTopLevelComponent, options.componentProps, options.hostComponentData, parentComponent?.setupScript, options.injectedData );
447+
let ancestorComponent = this.getAncestorComponentForData(options);
448+
let useGlobalData = this.useGlobalDataAtTopLevel(ancestorComponent);
449+
let nodeData = this.dataCascade.getData( useGlobalData, options.componentProps, options.hostComponentData, ancestorComponent?.setupScript, options.injectedData );
434450
let evaluatedAttributes = await AttributeSerializer.evaluateAttributesArray(attrs, nodeData, options.closestParentComponent);
435451
let finalAttributesObject = AttributeSerializer.mergeAttributes(evaluatedAttributes);
436452

@@ -473,7 +489,7 @@ class AstSerializer {
473489
return content;
474490
}
475491

476-
async transformContent(content, transformTypes, node, parentComponent, slots, options) {
492+
async transformContent(content, transformTypes, node, slots, options) {
477493
if(!transformTypes) {
478494
transformTypes = [];
479495
}
@@ -487,7 +503,9 @@ class AstSerializer {
487503
slotsText.default = this.getPreparsedRawTextContent(o.hostComponentNode, o);
488504
}
489505

490-
let context = this.dataCascade.getData(parentComponent.isTopLevelComponent, options.componentProps, options.currentTagAttributes, parentComponent?.setupScript, options.injectedData, {
506+
let ancestorComponent = this.getAncestorComponentForData(options);
507+
let useGlobalData = this.useGlobalDataAtTopLevel(ancestorComponent);
508+
let context = this.dataCascade.getData(useGlobalData, options.componentProps, options.currentTagAttributes, ancestorComponent?.setupScript, options.injectedData, {
491509
// Ideally these would be under `webc.*`
492510
filePath: this.filePath,
493511
slots: {
@@ -500,7 +518,7 @@ class AstSerializer {
500518
content = await this.transforms[type].call({
501519
type,
502520
...context
503-
}, content, parentComponent);
521+
}, content, ancestorComponent);
504522
}
505523

506524
return content;
@@ -615,7 +633,7 @@ class AstSerializer {
615633
return rawContent;
616634
}
617635

618-
return this.transformContent(rawContent, options.currentTransformTypes, node, this.componentManager.get(options.closestParentComponent), slots, options);
636+
return this.transformContent(rawContent, options.currentTransformTypes, node, slots, options);
619637
}
620638

621639
/**
@@ -754,8 +772,9 @@ class AstSerializer {
754772

755773
// Used for @html, @raw, @text, @attributes, webc:if, webc:elseif, webc:for
756774
async evaluateAttribute(name, attrContent, options) {
757-
let parentComponent = this.componentManager.get(options.closestParentComponent);
758-
let data = this.dataCascade.getData(parentComponent.isTopLevelComponent, options.componentProps, parentComponent?.setupScript, options.injectedData);
775+
let ancestorComponent = this.getAncestorComponentForData(options);
776+
let useGlobalData = this.useGlobalDataAtTopLevel(ancestorComponent);
777+
let data = this.dataCascade.getData(useGlobalData, options.componentProps, ancestorComponent?.setupScript, options.injectedData);
759778

760779
let { returns } = await ModuleScript.evaluateScriptInline(attrContent, data, `Check the dynamic attribute: \`${name}="${attrContent}"\`.`, options.closestParentComponent);
761780
return returns;
@@ -1008,7 +1027,7 @@ class AstSerializer {
10081027

10091028
// Run transforms
10101029
if(options.currentTransformTypes && options.currentTransformTypes.length > 0) {
1011-
c = await this.transformContent(node.value, options.currentTransformTypes, node, this.componentManager.get(options.closestParentComponent), slots, options);
1030+
c = await this.transformContent(node.value, options.currentTransformTypes, node, slots, options);
10121031

10131032
// only reprocess text nodes in a <* webc:is="template" webc:type>
10141033
if(!node._webCProcessed && node.parentNode && AstQuery.getTagName(node.parentNode) === "template") {
@@ -1096,7 +1115,7 @@ class AstSerializer {
10961115
// TODO warning if top level page component using a style hash but has no root element (text only?)
10971116

10981117
// Start tag
1099-
let { content: startTagContent, attrs, evaluatedAttributes, nodeData } = await this.renderStartTag(node, tagName, component, renderingMode, options);
1118+
let { content: startTagContent, attrs, nodeData } = await this.renderStartTag(node, tagName, component, renderingMode, options);
11001119
content += this.outputHtml(startTagContent, streamEnabled);
11011120

11021121
if(component) {
@@ -1192,7 +1211,7 @@ class AstSerializer {
11921211
if(externalSource) { // fetch file contents, note that child content of the node is ignored here
11931212
// We could check to make sure this isn’t already in the asset aggregation bucket *before* we read but that could result in out-of-date content
11941213
let fileContent = this.fileCache.read(externalSource, options.closestParentComponent || this.filePath);
1195-
childContent = await this.transformContent(fileContent, options.currentTransformTypes, node, this.componentManager.get(options.closestParentComponent), slots, options);
1214+
childContent = await this.transformContent(fileContent, options.currentTransformTypes, node, slots, options);
11961215
} else {
11971216
let { html } = await this.getChildContent(node, slots, options, false);
11981217
childContent = html;

src/dataCascade.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@ class DataCascade {
3434
* This prevents global data leaking into inner components.
3535
* Notably webc:setup always operates in top level component mode.
3636
*/
37-
getData(isTopLevelComponent, attributes, ...additionalObjects) {
37+
getData(useGlobalDataAtTopLevel, attributes, ...additionalObjects) {
3838
let self = this;
3939
let objs = additionalObjects.reverse();
40-
let globals = isTopLevelComponent ? this.globalData : undefined;
40+
let globals = useGlobalDataAtTopLevel ? this.globalData : undefined;
4141

4242
let ret = Object.assign({}, globals, this.helpers, ...objs, attributes, {
4343
get $data() {

test/issue-152-test.js

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import test from "ava";
2+
import { WebC } from "../webc.js";
3+
4+
test("Slotted global data access #152", async t => {
5+
let component = new WebC();
6+
7+
component.setBundlerMode(true);
8+
component.setInputPath("./test/stubs/issue-152/page.webc");
9+
component.defineComponents("./test/stubs/issue-152/site-card.webc");
10+
11+
let { html } = await component.compile({
12+
data: {
13+
globalData: "Hello"
14+
}
15+
});
16+
17+
t.is(html.trim(), `<site-card>Hello I am in the default slot.<span>Hello</span></site-card>`);
18+
});

test/stubs/issue-152/page.webc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<site-card>Hello I am in the default slot.<span @text="globalData"></span></site-card>

test/stubs/issue-152/site-card.webc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<style>/* hi */</style>

0 commit comments

Comments
 (0)