diff --git a/lib/actions/handleNames.js b/lib/actions/handleNames.js index 9892cad..168f843 100644 --- a/lib/actions/handleNames.js +++ b/lib/actions/handleNames.js @@ -141,6 +141,7 @@ const getExportsOrganizer = (fileSchemas) => { // Verifica se já tem os nomes de elementos no conteúdo anterior // exports = [...exports, ...getExportConsts(schema.content)]; + // TODO: melhorar isso usando Babel exports = [ ...getExportConsts(schema.content), ...getExportLets(schema.content), diff --git a/lib/actions/loadFilesInfo.js b/lib/actions/loadFilesInfo.js index c26767f..3c489f5 100644 --- a/lib/actions/loadFilesInfo.js +++ b/lib/actions/loadFilesInfo.js @@ -25,7 +25,8 @@ const prepareAlemDependencies = require("./prepareAlemDependencies"); const replaceStatefulReferencesToJSX = (initialFileSchema) => { let content = initialFileSchema.content; initialFileSchema.toImport.forEach((filePath) => { - let importItemContent = fs.readFileSync(filePath, "utf8"); + // let importItemContent = fs.readFileSync(filePath, "utf8"); + let importItemContent = filesContentCache.getFileContent(filePath); const importComponentName = helpers.getComponentName(importItemContent); const isImportStatefulComponent = hasWidgetPropsCheck( removeImports(importItemContent), @@ -250,7 +251,7 @@ const loadFilesInfo = (entryFile) => { const initialFileSchemas = _.cloneDeep(contentOrderer); // Handle names -> remove const duplicates - contentOrderer = handleNames(contentOrderer); + contentOrderer = handleNames(contentOrderer); // INFO: parte que esta consumindo bastante recurso return { hasError, diff --git a/lib/actions/transformSchemaToWidget.js b/lib/actions/transformSchemaToWidget.js index 7c0b166..894ce1d 100644 --- a/lib/actions/transformSchemaToWidget.js +++ b/lib/actions/transformSchemaToWidget.js @@ -330,6 +330,48 @@ const processSchema = (fileSchema) => { return fileSchema; }; +/** + * Processa os Widgets dentro das propriedades, como por exemplo a propriedade + * } /> + * onde o "A_192" é um Widget + * + * ATENCAO: Isso trata especificamente os casos em que um widget (stateful component) é encontrado + * nas propriedades + * + * @param {*} childProps + * @param {*} fileSchemas + * @returns + */ +const transformWidgetInChildProps = (childProps, fileSchemas) => { + const childPropEntries = Object.entries(childProps); + + childPropEntries.forEach((entry) => { + // Skip children prop + if (entry[0] === "children") { + return childProps; + } + + const entryKey = entry[0]; + let entryValue = entry[1]; + + // Ignora se nao tiver conteúdo JSX + if (!entryValue.includes("/>")) { + return; + } + + const foundJSXs = extractJSX(entryValue); + if (foundJSXs.length > 0) { + foundJSXs.forEach((jsx) => { + const widgetContent = processChildrenWidget(`<>${jsx}`, fileSchemas); + entryValue = entryValue.replace(jsx, widgetContent); + }); + } + childProps[entryKey] = entryValue; + }); + + return childProps; +}; + /** * Faz o procedimento de trocar componentes nome de componentes por * @@ -367,18 +409,15 @@ const swapComponentsForStatelessFiles = (fileSchemas, fileSchema) => { Object.keys(fileSchema.componentImportItems).forEach((importItem) => { // Se for um arquivo disponível, segue (null quer dizer que é um import de alguma lib nao local no src) const importItemFilePath = fileSchema.componentImportItems[importItem]; + // Nao deve processar (copiar e colar) o conteúdo do arquivo mais de uma vez if (importItemFilePath && !pastedFiles.includes(importItemFilePath)) { // Adiciona na lista de items ja processados pastedFiles.push(importItemFilePath); - // INFO: Verifica se o caminho do arquivo a ser processado não é "null" - const importItemFileSource = fileSchema.componentImportItems[importItem]; // src/path/to/file.tsx | null - // Le o nome do Widget dependente (usando o fileSchema dele) let importItemWidget = fileSchemas.find( - (importFileSchema) => - importFileSchema.filePath === importItemFileSource, + (importFileSchema) => importFileSchema.filePath === importItemFilePath, ); // MODULOS - INICIO @@ -403,108 +442,103 @@ const swapComponentsForStatelessFiles = (fileSchemas, fileSchema) => { // const rootHTML = parse(fileBundle, {}); // Files without source are the ones that not live in the src directory + // NOTE: Aqui que a magica acontece!!!! + + const importItemWidgetComponentName = + importItemWidget.widgetName || + getComponentName(importItemWidget.finalFileBundle); + + if (importItemWidgetComponentName && !importItemWidget.isStateless) { + // Processa todos os componentes filhos + // Cada elemento do mesmo tipo é um filho diferente que foi adicionado ao elemento pai + // const importItemElements = + // fileSchema.htmlElementsProps[importItemWidgetComponentName] || []; + + // Usa o rootHTML (conteúdo html do componente) para pegar a lista de Componentes do tipo desejado. ex: Title + // const componentElements = rootHTML.getElementsByTagName( + // importItemWidgetComponentName, + // ); + // INFO: Esses comentarios acima creio que podem ser apagados, verificar + // se ainda estou usando o modulo html parse + + const jsxOnly = extractJSX(fileSchema.content); + + const fixedJsxOnly = + jsxOnly.length > 1 + ? `<>${jsxOnly.join("\n")}` + : jsxOnly.join("\n"); + + const componentElements = extractJSXElements( + fixedJsxOnly, + importItemWidgetComponentName, + ); + + // Seta qualquer erro se tiver + if (!processError && componentElements.error) { + processError = `${fileSchema.filePath}: ${componentElements.error}`; + } + if (processError) return; - // // INFO: Verifica se o caminho do arquivo a ser processado não é "null" - // const importItemFileSource = - // fileSchema.componentImportItems[importItem]; // src/path/to/file.tsx | null + // Transfor cada componente em Widget com suas propriedades + componentElements.elements.forEach((div, divIndex) => { + const htmlElementString = componentElements.elements[divIndex] + .toString() + .replaceAll(LINE_BREAKS, "") + .replaceAll(MORE_THAN_ONE_SPACE, " "); - // Se existir o conteúdo localmente... segue... - if (importItemFileSource) { - // NOTE: Aqui que a magica acontece!!!! + const extractPropsResult = extractPropsFromJSX(htmlElementString); + let childProps = extractPropsResult.keyValueProps; - const importItemWidgetComponentName = - importItemWidget.widgetName || - getComponentName(importItemWidget.finalFileBundle); + const childSpreads = extractPropsResult.spreads; - if (importItemWidgetComponentName && !importItemWidget.isStateless) { - // Processa todos os componentes filhos - // Cada elemento do mesmo tipo é um filho diferente que foi adicionado ao elemento pai - // const importItemElements = - // fileSchema.htmlElementsProps[importItemWidgetComponentName] || []; + // get the children (pega o filho(s) do elemento principal) + let childChildren = extractJSXChildren(htmlElementString); - // Usa o rootHTML (conteúdo html do componente) para pegar a lista de Componentes do tipo desejado. ex: Title - // const componentElements = rootHTML.getElementsByTagName( - // importItemWidgetComponentName, - // ); - // INFO: Esses comentarios acima creio que podem ser apagados, verificar - // se ainda estou usando o modulo html parse + if (childChildren) { + childChildren = processChildrenWidget(childChildren, fileSchemas); + childProps = { ...childProps, children: childChildren }; + } + + // Processa os Widgets dentro das propriedades, como por exemplo a propriedade + // } /> + // onde o "A_192" é um Widget + childProps = transformWidgetInChildProps(childProps, fileSchemas); - const jsxOnly = extractJSX(fileSchema.content); + let importItemPropsStringSequence = + convertObjectToArray(childProps).join(","); + + // Adiciona os spreads junto com as propriedades do elemento JSX. Ex: + // 0) { + importItemPropsStringSequence += `${importItemPropsStringSequence.length > 0 ? "," : ""} ${childSpreads.join(",")}`; + } - const fixedJsxOnly = - jsxOnly.length > 1 - ? `<>${jsxOnly.join("\n")}` - : jsxOnly.join("\n"); + // Babel segue os padroes JS, por isso: + // 1 - Adiciona uma uma função no topo + // 2 - Fecha a função no final + fileBundle = `const TempMethod = () => {\n${fileBundle}\n}`; + // NOTE: nao adicionando a ultima linha, mas estou removendo a ultima linha + // Caso quebre, ver isso. [Provavelmente o escape acima esta adicionando o } no final] - const componentElements = extractJSXElements( - fixedJsxOnly, + // Transform components generated by .jsx / .tsx into + fileBundle = replaceJSXElement( + fileBundle, importItemWidgetComponentName, + 0, + ``, ); - // Seta qualquer erro se tiver - if (!processError && componentElements.error) { - processError = `${fileSchema.filePath}: ${componentElements.error}`; - } - if (processError) return; - - // Transfor cada componente em Widget com suas propriedades - componentElements.elements.forEach((div, divIndex) => { - const htmlElementString = componentElements.elements[divIndex] - .toString() - .replaceAll(LINE_BREAKS, "") - .replaceAll(MORE_THAN_ONE_SPACE, " "); - - const extractPropsResult = extractPropsFromJSX(htmlElementString); - let childProps = extractPropsResult.keyValueProps; - - const childSpreads = extractPropsResult.spreads; - - // get the children - let childChildren = extractJSXChildren(htmlElementString); - if (childChildren) { - childChildren = processChildrenWidget( - childChildren, - fileSchemas, - ); - childProps = { ...childProps, children: childChildren }; - } - - let importItemPropsStringSequence = - convertObjectToArray(childProps).join(","); - - // Adiciona os spreads junto com as propriedades do elemento JSX. Ex: - // 0) { - importItemPropsStringSequence += `${importItemPropsStringSequence.length > 0 ? "," : ""} ${childSpreads.join(",")}`; - } - - // Babel segue os padroes JS, por isso: - // 1 - Adiciona uma uma função no topo - // 2 - Fecha a função no final - fileBundle = `const TempMethod = () => {\n${fileBundle}\n}`; - // NOTE: nao adicionando a ultima linha, mas estou removendo a ultima linha - // Caso quebre, ver isso. [Provavelmente o escape acima esta adicionando o } no final] - - // Transform components generated by .jsx / .tsx into - fileBundle = replaceJSXElement( - fileBundle, - importItemWidgetComponentName, - 0, - ``, - ); - - // Remove funcao no topo e ultima linha fechando a funcao - fileBundle = fileBundle.replace("const TempMethod = () => {", ""); - fileBundle = removeLastLineFromText(fileBundle); - }); - } - - // Altera o jsContent com os Widgets - fileSchema.jsContent = fileBundle; - // Altera o finalBundle que é usado posteriormente - fileSchema.finalFileBundle = fileBundle; + // Remove funcao no topo e ultima linha fechando a funcao + fileBundle = fileBundle.replace("const TempMethod = () => {", ""); + fileBundle = removeLastLineFromText(fileBundle); + }); } + + // Altera o jsContent com os Widgets + fileSchema.jsContent = fileBundle; + // Altera o finalBundle que é usado posteriormente + fileSchema.finalFileBundle = fileBundle; } } }); diff --git a/lib/compiler.js b/lib/compiler.js index c120583..7b1efb5 100644 --- a/lib/compiler.js +++ b/lib/compiler.js @@ -1,4 +1,4 @@ -const { create_dist, log } = require("./utils"); +const { create_dist, log, reset_name_counter } = require("./utils"); const path = require("path"); const fs = require("fs"); const loadFilesInfo = require("./actions/loadFilesInfo"); @@ -126,6 +126,7 @@ function run_final_process(filesInfo, opts) { * @param {*} opts Opcoes da CLI */ function compile_files(opts) { + reset_name_counter(); create_dist(distFolder); let entryFile = path.join(".", "src", "index.tsx"); diff --git a/package.json b/package.json index 384b047..bdc4ffb 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "alem", "description": "Create web3 applications for NEAR BOS with a focus on performance and friendly development.", - "version": "1.0.0", + "version": "1.0.1", "main": "main.js", "types": "index.d.ts", "author": "Wenderson Pires - wendersonpires.near",