* Only available on the server and when compiling with the `server` option. * Takes a component and returns an object with `body` and `head` properties on it, which you can use to populate the HTML when server-rendering your app. * @template {Record<string, any>} Props * @param {Component<Prop
(component, options = {})
| 510 | * @returns {RenderOutput} |
| 511 | */ |
| 512 | static render(component, options = {}) { |
| 513 | /** @type {AccumulatedContent | undefined} */ |
| 514 | let sync; |
| 515 | /** @type {Promise<AccumulatedContent & { hashes: { script: Sha256Source[] } }> | undefined} */ |
| 516 | let async; |
| 517 | |
| 518 | const result = /** @type {RenderOutput} */ ({}); |
| 519 | // making these properties non-enumerable so that console.logging |
| 520 | // doesn't trigger a sync render |
| 521 | Object.defineProperties(result, { |
| 522 | html: { |
| 523 | get: () => { |
| 524 | return (sync ??= Renderer.#render(component, options)).body; |
| 525 | } |
| 526 | }, |
| 527 | head: { |
| 528 | get: () => { |
| 529 | return (sync ??= Renderer.#render(component, options)).head; |
| 530 | } |
| 531 | }, |
| 532 | body: { |
| 533 | get: () => { |
| 534 | return (sync ??= Renderer.#render(component, options)).body; |
| 535 | } |
| 536 | }, |
| 537 | hashes: { |
| 538 | value: { |
| 539 | script: '' |
| 540 | } |
| 541 | }, |
| 542 | then: { |
| 543 | value: |
| 544 | /** |
| 545 | * this is not type-safe, but honestly it's the best I can do right now, and it's a straightforward function. |
| 546 | * |
| 547 | * @template TResult1 |
| 548 | * @template [TResult2=never] |
| 549 | * @param { (value: SyncRenderOutput) => TResult1 } onfulfilled |
| 550 | * @param { (reason: unknown) => TResult2 } onrejected |
| 551 | */ |
| 552 | (onfulfilled, onrejected) => { |
| 553 | if (!async_mode_flag) { |
| 554 | const result = (sync ??= Renderer.#render(component, options)); |
| 555 | const user_result = onfulfilled({ |
| 556 | head: result.head, |
| 557 | body: result.body, |
| 558 | html: result.body, |
| 559 | hashes: { script: [] } |
| 560 | }); |
| 561 | return Promise.resolve(user_result); |
| 562 | } |
| 563 | async ??= init_render_context().then(() => |
| 564 | with_render_context(() => Renderer.#render_async(component, options)) |
| 565 | ); |
| 566 | return async.then((result) => { |
| 567 | Object.defineProperty(result, 'html', { |
| 568 | // eslint-disable-next-line getter-return |
| 569 | get: () => { |
no test coverage detected