POC rendering via queue
This commit is contained in:
parent
97f876abba
commit
b6748f3be9
2 changed files with 188 additions and 0 deletions
118
packages/astro/test/units/render/jsx.proto.js
Normal file
118
packages/astro/test/units/render/jsx.proto.js
Normal file
|
@ -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}>`;
|
||||
}
|
|
@ -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('<div><p class="n">works</p></div>');
|
||||
});
|
||||
|
||||
it('Can render slots', async () => {
|
||||
const Wrapper = createComponent((result, _props, slots = {}) => {
|
||||
return render`<div>${renderSlot(result, slots['myslot'])}</div>`;
|
||||
|
@ -117,3 +148,42 @@ describe('core/render', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('new engine', () => {
|
||||
it('orderRoot', () => {
|
||||
const root = {
|
||||
node: 'p',
|
||||
children: [
|
||||
{ node: 'span', children: [{ node: 'a', children: 'I am a link' }] },
|
||||
{
|
||||
node: 'span',
|
||||
children: [
|
||||
{ children: 'I am a text' },
|
||||
{ node: 'strong', children: 'I am strong' },
|
||||
{ node: 'em', children: 'I am em' },
|
||||
{ node: 'u', children: 'I am underline' },
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
const expected = [
|
||||
{ node: 'a', content: 'I am a link', parent: 'span' },
|
||||
{ node: 'span', parent: 'span' },
|
||||
{ content: 'I am a text', parent: 'span' },
|
||||
{ node: 'strong', content: 'I am strong', parent: 'span' },
|
||||
{ node: 'em', content: 'I am em', parent: 'span' },
|
||||
{ node: 'u', content: 'I am underline', parent: 'span' },
|
||||
{ node: 'span', parent: 'p' },
|
||||
{ node: 'p' },
|
||||
];
|
||||
|
||||
const expectedString = `<p><span><a>I am a link</a></span><span>I am a text<strong>I am strong</strong><em>I am em</em><u>I am underline</u></span></p>`;
|
||||
let result = orderRoot(root);
|
||||
|
||||
expect(result).to.deep.equal(expected);
|
||||
|
||||
let rendered = renderQueue(result);
|
||||
|
||||
expect(rendered).to.deep.equal(expectedString);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue