diff --git a/src-docs/src/components/guide_section/_utils.js b/src-docs/src/components/guide_section/_utils.js index e0b65ef2d04..ddce7322575 100644 --- a/src-docs/src/components/guide_section/_utils.js +++ b/src-docs/src/components/guide_section/_utils.js @@ -1,38 +1,63 @@ +/** + * renderJsSource code is responsible for formatting the JavaScript that goes into the DemoJS within the + * EUI Docs. In addition to formatting the code for the tab, this function also combines EUI imports by + * searching code.default for all EUI imports, extracting the variables, and combining them at the top of + * the formatted code. + */ + import { cleanEuiImports } from '../../services'; export const renderJsSourceCode = (code) => { - let renderedCode = cleanEuiImports(code.default).split('\n'); - const linesWithImport = []; - // eslint-disable-next-line guard-for-in - for (const idx in renderedCode) { - const line = renderedCode[idx]; - if (line.includes('import') && line.includes("from '@elastic/eui';")) { - linesWithImport.push(line); - renderedCode[idx] = ''; + let renderedCode = cleanEuiImports(code.default); + + /* ----- Combine and clean EUI imports ----- */ + let elasticImports = ['']; + + // Find all imports that come from '@elastic/eui' + renderedCode = renderedCode.replace( + // [\r\n] - start of a line + // import\s+\{ - import / whitespace / opening brace + // ([^}]+) - group together anything that isn't a closing brace + // \}\s+from\s+'@elastic\/eui'; - closing brace / whitespace / from / whitespace / '@elastic/eui'; + // [\r\n] - match end of line, so the extra new line is removed via the replace operation + /[\r\n]import\s+\{([^}]+)\}\s+from\s+'@elastic\/eui';/g, + (match, imports) => { + // remove any additional characters from imports + const namedImports = imports.match(/[a-zA-Z0-9]+/g); + elasticImports.push(...namedImports); + return ''; } + ); + + // Remove empty spaces in the array + elasticImports = elasticImports.filter((ele) => ele); + + let formattedEuiImports = ''; + + // determine if imports should be wrapped to new lines based on the import statement length + const combinedImports = elasticImports.join(', '); + const singleLineImports = `import { ${combinedImports} } from '@elastic/eui';`; + + if (singleLineImports.length <= 81) { + formattedEuiImports = singleLineImports; + } else { + const lineSeparatedImports = elasticImports.join(',\n '); + formattedEuiImports = `import {\n ${lineSeparatedImports},\n} from '@elastic/eui';`; } - if (linesWithImport.length > 1) { - linesWithImport[0] = linesWithImport[0].replace( - " } from '@elastic/eui';", - ',' - ); - for (let i = 1; i < linesWithImport.length - 1; i++) { - linesWithImport[i] = linesWithImport[i] - .replace('import {', '') - .replace(" } from '@elastic/eui';", ','); + + // Find any non-EUI imports and join them with new lines between each import for uniformity + const nonEuiImports = []; + + renderedCode = renderedCode.replace( + /import\s+([^]+?)\s+from\s+(\'[A-Za-z0-9 _./-]*\'\;)/g, + (match) => { + nonEuiImports.push(match); + return ''; } - linesWithImport[linesWithImport.length - 1] = linesWithImport[ - linesWithImport.length - 1 - ].replace('import {', ''); - } - const newImport = linesWithImport.join(''); - renderedCode.unshift(newImport); - renderedCode = renderedCode.join('\n'); - let len = renderedCode.replace('\n\n\n', '\n\n').length; - while (len < renderedCode.length) { - renderedCode = renderedCode.replace('\n\n\n', '\n\n'); - len = renderedCode.replace('\n\n\n', '\n\n').length; - } + ); + + const formattedNonEuiImports = nonEuiImports.join('\n'); - return renderedCode; + const fullyFormattedCode = `${formattedEuiImports}\n${formattedNonEuiImports}\n\n${renderedCode.trim()}`; + return fullyFormattedCode; };