UNPKG

2.83 kBJavaScriptView Raw
1'use strict';
2
3const parse5 = require('parse5');
4const treeAdapter = parse5.treeAdapters.htmlparser2;
5const CustomSerializer = require('./serializer');
6
7/**
8 * Handles the parsing and serialization of templates. Also takes care of
9 * merging the base and page templates
10 */
11
12module.exports = class Transform {
13 constructor(handleTags, insertBeforePipeTags) {
14 this.handleTags = handleTags;
15 this.pipeTags = insertBeforePipeTags;
16 }
17
18 /**
19 * Parse and serialize the html.
20 *
21 * @param {string} baseTemplate - Base template that contains all the necessary tags and fragments for the given page (Used by multiple pages)
22 * @param {string=} childTemplate - The current page template that gets merged in to the base template
23 * @returns {Array} Array consiting of Buffers and Objects
24 */
25 applyTransforms(baseTemplate, childTemplate, fullRendering) {
26 const options = { treeAdapter };
27 const rootNodes = fullRendering
28 ? parse5.parse(baseTemplate, options)
29 : parse5.parseFragment(baseTemplate, options);
30 const slotMap =
31 childTemplate && typeof childTemplate === 'string'
32 ? this._groupSlots(parse5.parseFragment(childTemplate, options))
33 : new Map();
34 const serializerOptions = {
35 treeAdapter,
36 slotMap,
37 pipeTags: this.pipeTags,
38 handleTags: this.handleTags,
39 fullRendering
40 };
41 const serializer = new CustomSerializer(rootNodes, serializerOptions);
42 return serializer.serialize();
43 }
44 /**
45 * Group all the nodes after parsing the child template. Nodes with unnamed slots are
46 * added to default slots
47 *
48 * @param {Object} root - The root node of the child template
49 * @returns {Map} Map with keys as slot attribute name and corresponding values consisting of array of matching nodes
50 */
51 _groupSlots(root) {
52 const slotMap = new Map([['default', []]]);
53 const nodes = treeAdapter.getChildNodes(root);
54 nodes.forEach(node => {
55 if (!treeAdapter.isTextNode(node)) {
56 const { slot = 'default' } = node.attribs;
57 const slotNodes = slotMap.get(slot) || [];
58 const updatedSlotNodes = [...slotNodes, node];
59 slotMap.set(slot, updatedSlotNodes);
60 this._pushText(node.next, updatedSlotNodes);
61 delete node.attribs.slot;
62 }
63 });
64 return slotMap;
65 }
66
67 /**
68 * Add the text node to the Slot Map
69 *
70 * @param {Object} nextNode
71 * @param {Array} slot - Array of matching nodes
72 */
73 _pushText(nextNode, slot) {
74 if (nextNode && treeAdapter.isTextNode(nextNode)) {
75 slot.push(nextNode);
76 }
77 }
78};