Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 31 additions & 12 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@ const extend = (options = {}) => tree => {

const blockNodes = getBlockNodes(options.slotTagName, tree);
for (const blockName of Object.keys(blockNodes)) {
const blockNode = blockNodes[blockName];
blockNode.tag = false;
blockNode.content = blockNode.content || [];
blockNodes[blockName] = blockNode;
const blockNodeList = blockNodes[blockName];
for (const blockNode of blockNodeList) {
blockNode.tag = false;
blockNode.content = blockNode.content || [];
}
blockNodes[blockName] = blockNodeList;
}

return tree;
Expand Down Expand Up @@ -81,17 +83,24 @@ function mergeExtendsAndLayout(layoutTree, extendsNode, strictNames, slotTagName
const extendsBlockNodes = getBlockNodes(fillTagName, extendsNode.content);

for (const layoutBlockName of Object.keys(layoutBlockNodes)) {
const extendsBlockNode = extendsBlockNodes[layoutBlockName];
const extendsBlockNodeList = extendsBlockNodes[layoutBlockName]
if (!extendsBlockNodeList) {
continue;
}
// pick up the last block node if multiple blocks are declared in `extends` node
const extendsBlockNode = extendsBlockNodeList[extendsBlockNodeList.length - 1];
if (!extendsBlockNode) {
continue;
}

const layoutBlockNode = layoutBlockNodes[layoutBlockName];
layoutBlockNode.content = mergeContent(
extendsBlockNode.content,
layoutBlockNode.content,
getBlockType(extendsBlockNode)
);
const layoutBlockNodeList = layoutBlockNodes[layoutBlockName];
for (const layoutBlockNode of layoutBlockNodeList) {
layoutBlockNode.content = mergeContent(
extendsBlockNode.content,
layoutBlockNode.content,
getBlockType(extendsBlockNode)
);
}

delete extendsBlockNodes[layoutBlockName];
}
Expand Down Expand Up @@ -146,13 +155,23 @@ function getBlockNodes(tag, content = []) {
throw getError(errors.BLOCK_NO_NAME);
}

blockNodes[node.attrs.name] = node;
appendBlockNode(blockNodes, node)
return node;
});

return blockNodes;
}

function appendBlockNode(blockNodes, node) {
const { name } = node.attrs
if (blockNodes[name] == null) {
blockNodes[name] = [node]
} else {
blockNodes[name].push(node)
}
return blockNodes
}

function getError(...rest) {
const message = format(...rest);
return new Error('[posthtml-extend] ' + message);
Expand Down
106 changes: 106 additions & 0 deletions test/extend.js
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,112 @@ describe('Extend', () => {
});
});

it('should extend layout with multiple blocks', () => {
mfs.writeFileSync('./layout.html', `
<div>
<block name="content"></block>
<hr>
<block name="content"></block>
<hr>
<block name="content"></block>
</div>
`)

return init(`
<extends src="layout.html">
<block name="content"><p>content</p></block>
</extends>
`).then(html => {
expect(html).toBe(cleanHtml(`
<div>
<p>content</p>
<hr>
<p>content</p>
<hr>
<p>content</p>
</div>
`))
});
});

it('should render the last <block> if multiple <block> tags with the same name are declared in <extends>', () => {
mfs.writeFileSync('./layout.html', `
<div>
<block name="content"></block>
<hr>
<block name="content"></block>
<hr>
<block name="content"></block>
</div>
`)

return init(`
<extends src="layout.html">
<block name="content"><p>1</p></block>
<block name="content"><p>2</p></block>
<block name="content"><p>3</p></block>
</extends>
`).then(html => {
expect(html).toBe(cleanHtml(`
<div>
<p>3</p>
<hr>
<p>3</p>
<hr>
<p>3</p>
</div>
`))
});
});

it('should extends layout multiple times', () => {
mfs.writeFileSync('./layout.html', `
<div>
<block name="content"></block>
<hr>
<block name="content"></block>
<hr>
<block name="content"></block>
</div>
`)

return init(`
<extends src="layout.html">
<block name="content"><p>1</p></block>
</extends>
<extends src="layout.html">
<block name="content"><p>2</p></block>
</extends>
<extends src="layout.html">
<block name="content"><p>3</p></block>
</extends>
`).then(html => {
expect(html).toBe(cleanHtml(`
<div>
<p>1</p>
<hr>
<p>1</p>
<hr>
<p>1</p>
</div>
<div>
<p>2</p>
<hr>
<p>2</p>
<hr>
<p>2</p>
</div>
<div>
<p>3</p>
<hr>
<p>3</p>
<hr>
<p>3</p>
</div>
`))
});
});

it('should throw an error if <extends> has no "src"', () => {
return assertError(
init('<extends><block name="content"></block></extends>'),
Expand Down