diff --git a/packages/astro/test/units/render/jsx.proto.js b/packages/astro/test/units/render/jsx.proto.js new file mode 100644 index 000000000..2333c369c --- /dev/null +++ b/packages/astro/test/units/render/jsx.proto.js @@ -0,0 +1,118 @@ +/** + * We take a root as function and we start creating a quue + */ +export function orderRoot(root) { + const queue = [root]; + let result = []; + let previousNode; + // we apply a do/while because we need to process the root first + do { + // we pop elements from the back + let currentNode = queue.pop(); + if (Array.isArray(currentNode.children)) { + // if we have children, we fill the queue + queue.push(...currentNode.children); + const newNode = {}; + if (currentNode.node) { + newNode.node = currentNode.node; + } + // we need to create a new data structure were we need to keep track of the parent of each node + // the root doesn't have any parent + if (previousNode) { + newNode.parent = previousNode.node; + } + // track the previous node + previousNode = currentNode; + // fill the new node + result.push(newNode); + } else { + // usually here we have leafs and "children" should be just a string + const newNode = { content: currentNode.children }; + if (currentNode.node) { + newNode.node = currentNode.node; + } + if (previousNode) { + newNode.parent = previousNode.node; + } + result.push(newNode); + } + } while (queue.length > 0); + + return result.reverse(); +} + +export function renderQueue(queue) { + let html = ''; + let previousParent; + while (queue.length > 0) { + let element = queue.shift(); + if (!element.parent) { + html = `<${element.node}>${html}${element.node}>`; + break; + } + if (!previousParent) { + if (element.node) { + html += renderElement(element.node, element.content); + } else { + html += element.content; + } + previousParent = element.parent; + continue; + } + if (previousParent === element.node) { + if (element.content) { + if (element.node) { + html += renderElement(element.node, element.content); + } else { + html += element.content; + } + } else { + html = `<${element.node}>${html}${element.node}>`; + } + } else { + let [side, parent] = renderUntilElement(element, queue, element.parent); + previousParent = parent; + html += side; + } + + previousParent = element.parent; + } + return html; +} + +function renderUntilElement(previousElement, iterator, parent) { + let html = ''; + let previousParent; + if (previousElement.content) { + if (previousElement.node) { + html += renderElement(previousElement.node, previousElement.content); + } else { + html += previousElement.content; + } + } else { + html = renderElement(previousElement.node, html); + } + while (iterator.length > 0) { + let element = iterator.shift(); + if (element.node === parent) { + html = renderElement(element.node, html); + previousParent = element.node; + break; + } else { + if (element.content) { + if (element.node) { + html += renderElement(element.node, element.content); + } else { + html += element.content; + } + } else { + html = renderElement(element.node, html); + } + } + } + return [html, previousParent]; +} + +function renderElement(node, content) { + return `<${node}>${content}${node}>`; +} diff --git a/packages/astro/test/units/render/jsx.test.js b/packages/astro/test/units/render/jsx.test.js index a34b6b53b..8528c8902 100644 --- a/packages/astro/test/units/render/jsx.test.js +++ b/packages/astro/test/units/render/jsx.test.js @@ -15,6 +15,7 @@ import { } from '../../../dist/core/render/index.js'; import { createAstroJSXComponent, renderer as jsxRenderer } from '../../../dist/jsx/index.js'; import { defaultLogging as logging } from '../../test-utils.js'; +import { orderRoot, renderQueue } from './jsx.proto.js'; const createAstroModule = (AstroComponent) => ({ default: AstroComponent }); const loadJSXRenderer = () => loadRenderer(jsxRenderer, (s) => import(s)); @@ -29,6 +30,36 @@ describe('core/render', () => { }); }); + it('new rendering order', async () => { + const Page = createAstroJSXComponent(() => { + return jsx('main', { + children: [ + jsx('p', { + className: 'n', + children: [ + jsx('span', { + children: 'label 1', + }), + ' ', + jsx('span', { + children: 'label 2', + }), + ], + }), + ], + }); + }); + + const ctx = createRenderContext({ request: new Request('http://example.com/') }); + const response = await renderPage(createAstroModule(Page), ctx, env); + + expect(response.status).to.equal(200); + + const html = await response.text(); + console.log(html); + expect(html).to.include('
works
I am a linkI am a textI am strongI am emI am underline
`; + let result = orderRoot(root); + + expect(result).to.deep.equal(expected); + + let rendered = renderQueue(result); + + expect(rendered).to.deep.equal(expectedString); + }); +});