Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | 5x 5x 9x 9x 9x 9x 9x 9x 5x 6x 37x 14x 3x 11x 34x 34x 9x 57x 9x 9x 27x 19x 27x 27x 7x 8x 7x 7x 7x 7x 7x 9x 9x 9x 9x 9x | import {
type ComponentMetadata,
type StructureMetadata,
type SlotMetadata,
PropMetadata,
ComposedComponentMetadata,
} from '@fds-uif/generator-base';
import { serialize, defaultTreeAdapter, html } from 'parse5';
import type { DefaultTreeAdapterMap, Token } from 'parse5';
import { uppercaseFirstChar } from './utils/uppercaseFirstChar.js';
const NS = html.NS;
const treeAdapter = defaultTreeAdapter;
function createDocument() {
// Create an empty document
const document = treeAdapter.createDocument();
// Create template element
const templateElement = treeAdapter.createElement('template', NS.HTML, []) as DefaultTreeAdapterMap['template'];
// Create an empty content fragment for the template
const templateContent = treeAdapter.createDocumentFragment();
// Associate the content fragment with the template
treeAdapter.setTemplateContent(templateElement, templateContent);
// Build the document structure
treeAdapter.appendChild(document, templateElement);
// More intutiive template -> #document-fragment -> elements
return { document, template: templateContent };
}
const kebabToCamel = (str: string) => str.replace(/-([a-z])/g, (group) => group.slice(-1).toUpperCase());
function createChildren(parent: DefaultTreeAdapterMap['parentNode'], parentNode: (null | SlotMetadata | StructureMetadata | ComposedComponentMetadata), children: (SlotMetadata | StructureMetadata | ComposedComponentMetadata)[], props: PropMetadata[]): void {
if (!children || children.length === 0) {
return;
}
children.forEach((child) => {
if (child.hasOwnProperty('type') && (child as SlotMetadata).type === 'slot') {
const slot = child as SlotMetadata;
if (parent.nodeName === 'svg') {
console.log('LWC does not support svg>slot nesting');
throw new Error('LWC does not support svg>slot nesting');
}
if (slot.name === 'default') {
treeAdapter.appendChild(parent, treeAdapter.createElement('slot', NS.HTML, []));
} else {
treeAdapter.appendChild(parent, treeAdapter.createElement('slot', NS.HTML, [
{ name: 'name', value: slot.name },
]));
}
} else {
const node = child as StructureMetadata;
// static attributes and binding
const bound = (node.boundAttributes ?? []).map((api) => {
const knownApi = props.find((prop) => {
return prop.name === api.prop;
});
if (!knownApi) {
return null;
}
return { name: api.attribute, value: `{${knownApi.name}}` };
}).filter(x => x !== null);
if (node.element) {
const newElement = treeAdapter.createElement(node.element, NS.HTML, [
...Object.entries(node.attributes).map(([attribute, value]) => {
return { name: attribute, value: value } as Token.Attribute;
}),
...bound
]);
treeAdapter.appendChild(parent, newElement);
// recursively create children
createChildren(newElement, node, node.children, props);
} else if (node.conditionals && node.conditionals.length > 0) {
node.conditionals.forEach((condition) => {
const lwcCondition = condition.condition.split(' || ').map(x => uppercaseFirstChar(x)).join('Or');
const templateElement = treeAdapter.createElement('template', NS.HTML, [{
name: 'lwc:if',
value: `{hasSlot${lwcCondition}}`
}]) as DefaultTreeAdapterMap['template'];
const templateContent = treeAdapter.createDocumentFragment();
treeAdapter.setTemplateContent(templateElement, templateContent);
treeAdapter.appendChild(parent, templateElement);
createChildren(templateContent, condition.trueBranch, [condition.trueBranch], props);
});
}
}
});
}
export function generateTemplate(metadata: ComponentMetadata): string {
//console.log(JSON.stringify(metadata, undefined, ' '));
// create an empty document with a template element
const { document, template } = createDocument();
// loop metadata.structure.children and add them to the the template
createChildren(template, null, [metadata.structure], metadata.props);
// serialize the document to a string
let raw = serialize(document);
// ="{...}" to {} syntax
raw = raw.replace(/="(\{\w+\})"/g, '=$1');
// lwc:if="{...}" to {} syntax
//raw = raw.replace(/lwc:(if|else)="(\{[^\}]+\})"/g, 'lwc:$1=$2');
return raw;
}
|