UNPKG

@andersundsehr/storybook-typo3

Version:

The one and only Storybook Renderer for TYPO3 Fluid Components

119 lines (118 loc) 5.03 kB
function convertValueToString(key, argType, value, inline) { const createValue = () => { if ('variableName' in value) { if (inline) { return value.variableName; // For inline code, just return the variable name } return '{' + value.variableName + '}'; // For attributes, return the variable name wrapped in curly braces } const valueAsString = String(value.value); if (typeof value.value === 'boolean') { if (inline) { return valueAsString; } return '{' + valueAsString + '}'; } if (typeof value.value === 'number') { if (argType?.type?.name === 'int') { return String(Number.parseInt(valueAsString, 10)); // Convert to integer } return String(Number.parseFloat(valueAsString)); // Convert to float } if (inline) { return '\'' + valueAsString.replace(/'/g, '\\\'') + '\''; // Escape single quotes for inline code } return valueAsString.replace(/"/g, '\\"'); // Escape double quotes for attributes }; if (inline) { return key + ': ' + createValue(); } return key + '="' + createValue() + '"'; } function inlineCode(viewHelperArguments, component, defaultSlotContent) { const argsStrings = Object.entries(viewHelperArguments) .map(([argumentName, argumentValue]) => convertValueToString(argumentName, component.argTypes[argumentName], argumentValue, true)); const argsString = argsStrings.join(', '); let source = '{'; if (defaultSlotContent) { defaultSlotContent = defaultSlotContent.replace(/'/g, '\\\''); // Escape single quotes for inline code source += `'${defaultSlotContent}' -> `; } source += `${component.fullName}(`; if ((source.length + argsString.length) > 80) { source += `\n ${argsStrings.join(',\n ')}\n`; } else { source += argsString; } source += ')}'; return source; } function generateOpenTag(viewHelperArguments, component) { const argStrings = Object.entries(viewHelperArguments) .map(([argumentName, argumentValue]) => convertValueToString(argumentName, component.argTypes[argumentName], argumentValue, false)); let argsString = argStrings.join(' '); let openTag = `<${component.fullName}`; if (argsString.length > 0) { openTag += ' ' + argsString; } if (openTag.length > 80) { argsString = argStrings.join('\n '); openTag = `<${component.fullName} \n ${argsString}\n`; } return openTag; } const SLOT_PREFIX = 'slot____'; function createComponentData(component, args) { const viewHelperArguments = {}; const slots = {}; for (const [key, value] of Object.entries(args)) { if (key.startsWith(SLOT_PREFIX)) { // This is a slot const slotName = key.replace(SLOT_PREFIX, ''); if (value === null || value === undefined || value === '') { continue; } slots[slotName] = value; continue; } if (!key.includes('__')) { // This is a normal argument without virtual subkey viewHelperArguments[key] = { value }; continue; } // This is a virtual argument const [variableName] = key.split('__'); viewHelperArguments[variableName] = { variableName }; } return { viewHelperArguments, slots }; } export function convertComponentToSource(component, args) { const { viewHelperArguments, slots } = createComponentData(component, args); let source = ''; source += `<html\n xmlns:${component.namespace}="http://typo3.org/ns/${component.collection.replace(/\\/g, '/')}"\n data-namespace-typo3-fluid="true"\n>\n\n`; const usedArgs = [...new Set(Object.keys(args).filter(key => !key.startsWith(SLOT_PREFIX)).map(key => key.split('__')[0]))]; source += generateOpenTag(viewHelperArguments, component); if (Object.keys(slots).length <= 0) { source += `/>\n`; source += `\n<!-- or -->\n\n`; source += `{namespace ${component.namespace}=${component.collection}}\n\n`; source += inlineCode(viewHelperArguments, component); return source; } source += '>\n'; if (Object.keys(slots).length === 1 && slots.default) { // If there is only a default slot, we can use the inline code source += ` ${slots.default}\n`; source += '</' + component.fullName + '>\n'; source += `\n<!-- or -->\n\n`; source += `{namespace ${component.namespace}=${component.collection}}\n\n`; source += inlineCode(viewHelperArguments, component, slots.default); return source; } for (const [slotName, slotValue] of Object.entries(slots)) { source += ` <f:fragment name="${slotName}">${slotValue}</f:fragment>\n`; } source += '</' + component.fullName + '>'; return source; }