(_options = {})
| 594 | // TODO: props support via custom elements |
| 595 | export const componentToHtml: TranspilerGenerator<ToHtmlOptions> = |
| 596 | (_options = {}) => |
| 597 | ({ component }) => { |
| 598 | const options: InternalToHtmlOptions = initializeOptions({ |
| 599 | target: 'html', |
| 600 | component, |
| 601 | defaults: { |
| 602 | ..._options, |
| 603 | onChangeJsById: {}, |
| 604 | js: '', |
| 605 | namesMap: {}, |
| 606 | format: 'script', |
| 607 | }, |
| 608 | }); |
| 609 | let json = fastClone(component); |
| 610 | if (options.plugins) { |
| 611 | json = runPreJsonPlugins({ json, plugins: options.plugins }); |
| 612 | } |
| 613 | addUpdateAfterSet(json, options); |
| 614 | const componentHasProps = hasProps(json); |
| 615 | |
| 616 | const hasLoop = hasComponent('For', json); |
| 617 | const hasShow = hasComponent('Show', json); |
| 618 | const hasTextBinding = hasBindingsText(json); |
| 619 | |
| 620 | if (options.plugins) { |
| 621 | json = runPostJsonPlugins({ json, plugins: options.plugins }); |
| 622 | } |
| 623 | const css = collectCss(json, { |
| 624 | prefix: options.prefix, |
| 625 | }); |
| 626 | |
| 627 | let str = json.children.map((item) => blockToHtml(item, options)).join('\n'); |
| 628 | |
| 629 | if (css.trim().length) { |
| 630 | str += `<style>${css}</style>`; |
| 631 | } |
| 632 | |
| 633 | const hasChangeListeners = Boolean(Object.keys(options.onChangeJsById).length); |
| 634 | const hasGeneratedJs = Boolean(options.js.trim().length); |
| 635 | |
| 636 | if (hasChangeListeners || hasGeneratedJs || json.hooks.onMount.length || hasLoop) { |
| 637 | // TODO: collectJs helper for here and liquid |
| 638 | str += ` |
| 639 | <script> |
| 640 | (() => { |
| 641 | const state = ${getStateObjectStringFromComponent(json, { |
| 642 | valueMapper: (value) => |
| 643 | addUpdateAfterSetInCode(updateReferencesInCode(value, options), options), |
| 644 | })}; |
| 645 | ${componentHasProps ? `let props = {};` : ''} |
| 646 | let context = null; |
| 647 | let nodesToDestroy = []; |
| 648 | let pendingUpdate = false; |
| 649 | ${!json.hooks?.onInit?.code ? '' : 'let onInitOnce = false;'} |
| 650 | |
| 651 | function destroyAnyNodes() { |
| 652 | // destroy current view template refs before rendering again |
| 653 | nodesToDestroy.forEach(el => el.remove()); |
no test coverage detected