UNPKG

5.39 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.computesTemplateSourceFromComponent = exports.computesTemplateFromComponent = void 0;
4const NgComponentAnalyzer_1 = require("./utils/NgComponentAnalyzer");
5const separateInputsOutputsAttributes = (ngComponentInputsOutputs, props = {}) => {
6 const inputs = ngComponentInputsOutputs.inputs
7 .filter((i) => i.templateName in props)
8 .map((i) => i.templateName);
9 const outputs = ngComponentInputsOutputs.outputs
10 .filter((o) => o.templateName in props)
11 .map((o) => o.templateName);
12 return {
13 inputs,
14 outputs,
15 otherProps: Object.keys(props).filter((k) => ![...inputs, ...outputs].includes(k)),
16 };
17};
18/**
19 * Converts a component into a template with inputs/outputs present in initial props
20 * @param component
21 * @param initialProps
22 * @param innerTemplate
23 */
24exports.computesTemplateFromComponent = (component, initialProps, innerTemplate = '') => {
25 const ngComponentMetadata = NgComponentAnalyzer_1.getComponentDecoratorMetadata(component);
26 const ngComponentInputsOutputs = NgComponentAnalyzer_1.getComponentInputsOutputs(component);
27 if (!ngComponentMetadata.selector) {
28 // Allow to add renderer component when NgComponent selector is undefined
29 return `<ng-container *ngComponentOutlet="storyComponent"></ng-container>`;
30 }
31 const { inputs: initialInputs, outputs: initialOutputs } = separateInputsOutputsAttributes(ngComponentInputsOutputs, initialProps);
32 const templateInputs = initialInputs.length > 0 ? ` ${initialInputs.map((i) => `[${i}]="${i}"`).join(' ')}` : '';
33 const templateOutputs = initialOutputs.length > 0
34 ? ` ${initialOutputs.map((i) => `(${i})="${i}($event)"`).join(' ')}`
35 : '';
36 return buildTemplate(ngComponentMetadata.selector, innerTemplate, templateInputs, templateOutputs);
37};
38const createAngularInputProperty = ({ propertyName, value, argType, }) => {
39 const { name: type = null, summary = null } = (argType === null || argType === void 0 ? void 0 : argType.type) || {};
40 let templateValue = type === 'enum' && !!summary ? `${summary}.${value}` : value;
41 const actualType = type === 'enum' && summary ? 'enum' : typeof value;
42 const requiresBrackets = ['object', 'any', 'boolean', 'enum', 'number'].includes(actualType);
43 if (typeof value === 'object') {
44 templateValue = propertyName;
45 }
46 return `${requiresBrackets ? '[' : ''}${propertyName}${requiresBrackets ? ']' : ''}="${templateValue}"`;
47};
48/**
49 * Converts a component into a template with inputs/outputs present in initial props
50 * @param component
51 * @param initialProps
52 * @param innerTemplate
53 */
54exports.computesTemplateSourceFromComponent = (component, initialProps, argTypes) => {
55 const ngComponentMetadata = NgComponentAnalyzer_1.getComponentDecoratorMetadata(component);
56 if (!ngComponentMetadata) {
57 return null;
58 }
59 if (!ngComponentMetadata.selector) {
60 // Allow to add renderer component when NgComponent selector is undefined
61 return `<ng-container *ngComponentOutlet="${component.name}"></ng-container>`;
62 }
63 const ngComponentInputsOutputs = NgComponentAnalyzer_1.getComponentInputsOutputs(component);
64 const { inputs: initialInputs, outputs: initialOutputs } = separateInputsOutputsAttributes(ngComponentInputsOutputs, initialProps);
65 const templateInputs = initialInputs.length > 0
66 ? ` ${initialInputs
67 .map((propertyName) => createAngularInputProperty({
68 propertyName,
69 value: initialProps[propertyName],
70 argType: argTypes === null || argTypes === void 0 ? void 0 : argTypes[propertyName],
71 }))
72 .join(' ')}`
73 : '';
74 const templateOutputs = initialOutputs.length > 0
75 ? ` ${initialOutputs.map((i) => `(${i})="${i}($event)"`).join(' ')}`
76 : '';
77 return buildTemplate(ngComponentMetadata.selector, '', templateInputs, templateOutputs);
78};
79const buildTemplate = (selector, innerTemplate, inputs, outputs) => {
80 // https://www.w3.org/TR/2011/WD-html-markup-20110113/syntax.html#syntax-elements
81 const voidElements = [
82 'area',
83 'base',
84 'br',
85 'col',
86 'command',
87 'embed',
88 'hr',
89 'img',
90 'input',
91 'keygen',
92 'link',
93 'meta',
94 'param',
95 'source',
96 'track',
97 'wbr',
98 ];
99 const firstSelector = selector.split(',')[0];
100 const templateReplacers = [
101 [/(^.*?)(?=[,])/, '$1'],
102 [/(^\..+)/, 'div$1'],
103 [/(^\[.+?])/, 'div$1'],
104 [/([\w[\]]+)(\s*,[\w\s-[\],]+)+/, `$1`],
105 [/#([\w-]+)/, ` id="$1"`],
106 [/((\.[\w-]+)+)/, (_, c) => ` class="${c.split `.`.join ` `.trim()}"`],
107 [/(\[.+?])/g, (_, a) => ` ${a.slice(1, -1)}`],
108 [
109 /([\S]+)(.*)/,
110 (template, elementSelector) => {
111 return voidElements.some((element) => elementSelector === element)
112 ? template.replace(/([\S]+)(.*)/, `<$1$2${inputs}${outputs} />`)
113 : template.replace(/([\S]+)(.*)/, `<$1$2${inputs}${outputs}>${innerTemplate}</$1>`);
114 },
115 ],
116 ];
117 return templateReplacers.reduce((prevSelector, [searchValue, replacer]) => prevSelector.replace(searchValue, replacer), firstSelector);
118};