loopwind 0.16.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/default-templates/AGENTS.md +18 -2
- package/dist/lib/renderer.d.ts +6 -1
- package/dist/lib/renderer.d.ts.map +1 -1
- package/dist/lib/renderer.js +9 -9
- package/dist/lib/renderer.js.map +1 -1
- package/dist/lib/video-renderer.d.ts +3 -0
- package/dist/lib/video-renderer.d.ts.map +1 -1
- package/dist/lib/video-renderer.js +7 -7
- package/dist/lib/video-renderer.js.map +1 -1
- package/dist/sdk/index.d.ts +5 -3
- package/dist/sdk/index.d.ts.map +1 -1
- package/dist/sdk/index.js +30 -9
- package/dist/sdk/index.js.map +1 -1
- package/dist/sdk/template.d.ts +136 -0
- package/dist/sdk/template.d.ts.map +1 -1
- package/dist/sdk/template.js +198 -0
- package/dist/sdk/template.js.map +1 -1
- package/examples/code-editor-templates.ts +173 -0
- package/examples/nextjs-template-import.ts +58 -0
- package/examples/visual-builder-templates.ts +336 -0
- package/package.json +1 -1
- package/test-font-files.mjs +72 -0
- package/test-sdk-config.mjs +397 -0
- package/test-sdk-user-templates.mjs +469 -0
- package/website/.astro/integrations/_inox-tools_astro-when/types.d.ts +1 -0
- package/website/.astro/types.d.ts +1 -0
- package/website/DEPLOYMENT.md +142 -0
- package/website/OG_IMAGES.md +141 -0
- package/website/README.md +39 -19
- package/website/deploy.sh +19 -0
- package/website/dist/.gitkeep +1 -0
- package/website/dist/_astro/agents.Yx-L_igG.css +1 -0
- package/website/dist/_routes.json +30 -0
- package/website/dist/_worker.js/_@astrojs-ssr-adapter.mjs +1033 -0
- package/website/dist/_worker.js/_astro-internal_middleware.mjs +40 -0
- package/website/dist/_worker.js/chunks/abap_BTmsHiP5.mjs +1 -0
- package/website/dist/_worker.js/chunks/actionscript-3_DmBelb1E.mjs +1 -0
- package/website/dist/_worker.js/chunks/ada_8-E0ahCN.mjs +1 -0
- package/website/dist/_worker.js/chunks/andromeeda_XI-CXx50.mjs +1 -0
- package/website/dist/_worker.js/chunks/angular-html_DKGh3gGH.mjs +1 -0
- package/website/dist/_worker.js/chunks/angular-ts_-qZGsJoA.mjs +1 -0
- package/website/dist/_worker.js/chunks/apache_ijTUt0Ee.mjs +1 -0
- package/website/dist/_worker.js/chunks/apex_agu1c6Sh.mjs +1 -0
- package/website/dist/_worker.js/chunks/apl_Bj2f7Art.mjs +1 -0
- package/website/dist/_worker.js/chunks/applescript_B_vXrOh3.mjs +1 -0
- package/website/dist/_worker.js/chunks/ara_DCEQ2rnh.mjs +1 -0
- package/website/dist/_worker.js/chunks/asciidoc_CGN_EkYS.mjs +1 -0
- package/website/dist/_worker.js/chunks/asm_BBWZgnDp.mjs +1 -0
- package/website/dist/_worker.js/chunks/astro/assets-service_j52rQLzU.mjs +721 -0
- package/website/dist/_worker.js/chunks/astro/server_Y5_QHO8v.mjs +2401 -0
- package/website/dist/_worker.js/chunks/astro-designed-error-pages_BNTLO-TA.mjs +542 -0
- package/website/dist/_worker.js/chunks/astro_Dr_hht3h.mjs +1 -0
- package/website/dist/_worker.js/chunks/aurora-x_9GHG8nSq.mjs +1 -0
- package/website/dist/_worker.js/chunks/awk_DHRvhXot.mjs +1 -0
- package/website/dist/_worker.js/chunks/ayu-dark_CcvqmEHE.mjs +1 -0
- package/website/dist/_worker.js/chunks/ballerina_C7SdeSZb.mjs +1 -0
- package/website/dist/_worker.js/chunks/bat_Dv4A3u45.mjs +1 -0
- package/website/dist/_worker.js/chunks/beancount_BfPf9Luv.mjs +1 -0
- package/website/dist/_worker.js/chunks/berry_B8rfM3lL.mjs +1 -0
- package/website/dist/_worker.js/chunks/bibtex_TcjYgtJM.mjs +1 -0
- package/website/dist/_worker.js/chunks/bicep_CrlFWCdN.mjs +1 -0
- package/website/dist/_worker.js/chunks/blade_lanKVYID.mjs +1 -0
- package/website/dist/_worker.js/chunks/bsl_BhppzXMB.mjs +1 -0
- package/website/dist/_worker.js/chunks/c_6FBALJTK.mjs +1 -0
- package/website/dist/_worker.js/chunks/cadence_2txU9LVE.mjs +1 -0
- package/website/dist/_worker.js/chunks/cairo_BkrFAIlP.mjs +1 -0
- package/website/dist/_worker.js/chunks/catppuccin-frappe_CkEqIYhU.mjs +1 -0
- package/website/dist/_worker.js/chunks/catppuccin-latte_DG4Gx_-v.mjs +1 -0
- package/website/dist/_worker.js/chunks/catppuccin-macchiato_Cwi3vCXf.mjs +1 -0
- package/website/dist/_worker.js/chunks/catppuccin-mocha_L9_OPlFX.mjs +1 -0
- package/website/dist/_worker.js/chunks/clarity_BEAe4Ulu.mjs +1 -0
- package/website/dist/_worker.js/chunks/clojure_VnUX6p2g.mjs +1 -0
- package/website/dist/_worker.js/chunks/cmake_0-SGkZEj.mjs +1 -0
- package/website/dist/_worker.js/chunks/cobol_92M_KGaE.mjs +1 -0
- package/website/dist/_worker.js/chunks/codeowners_CzMwskBv.mjs +1 -0
- package/website/dist/_worker.js/chunks/codeql_DWJZNHv1.mjs +1 -0
- package/website/dist/_worker.js/chunks/coffee_CQjKU2fh.mjs +1 -0
- package/website/dist/_worker.js/chunks/common-lisp_BBLWDpS5.mjs +1 -0
- package/website/dist/_worker.js/chunks/coq_hedRFV3D.mjs +1 -0
- package/website/dist/_worker.js/chunks/cpp_DlS1i6Zs.mjs +1 -0
- package/website/dist/_worker.js/chunks/crystal_D6n65fKV.mjs +1 -0
- package/website/dist/_worker.js/chunks/csharp_C6FCVFzc.mjs +1 -0
- package/website/dist/_worker.js/chunks/css_C5uJEgmJ.mjs +1 -0
- package/website/dist/_worker.js/chunks/csv_CtMYuuJl.mjs +1 -0
- package/website/dist/_worker.js/chunks/cue_BsPexqx6.mjs +1 -0
- package/website/dist/_worker.js/chunks/cypher_apzf6OBi.mjs +1 -0
- package/website/dist/_worker.js/chunks/d_DcvIRcgm.mjs +1 -0
- package/website/dist/_worker.js/chunks/dark-plus_C01ONtzj.mjs +1 -0
- package/website/dist/_worker.js/chunks/dart_WkzM5WrV.mjs +1 -0
- package/website/dist/_worker.js/chunks/dax_DjXAO5V4.mjs +1 -0
- package/website/dist/_worker.js/chunks/desktop_C92LCxdc.mjs +1 -0
- package/website/dist/_worker.js/chunks/diff_CVwM_9XJ.mjs +1 -0
- package/website/dist/_worker.js/chunks/docker_DPzgJf6Z.mjs +1 -0
- package/website/dist/_worker.js/chunks/dotenv_D_vgANvA.mjs +1 -0
- package/website/dist/_worker.js/chunks/dracula-soft_CLnUBwFm.mjs +1 -0
- package/website/dist/_worker.js/chunks/dracula_lBVpb6Lb.mjs +1 -0
- package/website/dist/_worker.js/chunks/dream-maker_DTLbzd_J.mjs +1 -0
- package/website/dist/_worker.js/chunks/edge_i54JYm3_.mjs +1 -0
- package/website/dist/_worker.js/chunks/elixir_BJCIjTu4.mjs +1 -0
- package/website/dist/_worker.js/chunks/elm_BbXD39-_.mjs +1 -0
- package/website/dist/_worker.js/chunks/emacs-lisp_pxa5cXaN.mjs +1 -0
- package/website/dist/_worker.js/chunks/erb_Ccjijeee.mjs +1 -0
- package/website/dist/_worker.js/chunks/erlang_B2VM_hi7.mjs +1 -0
- package/website/dist/_worker.js/chunks/everforest-dark_BxvIPBim.mjs +1 -0
- package/website/dist/_worker.js/chunks/everforest-light_B7VoyaJM.mjs +1 -0
- package/website/dist/_worker.js/chunks/fennel_D-uo7X6c.mjs +1 -0
- package/website/dist/_worker.js/chunks/fish_BjePoK3m.mjs +1 -0
- package/website/dist/_worker.js/chunks/fluent_C8fgkzLX.mjs +1 -0
- package/website/dist/_worker.js/chunks/fortran-fixed-form_D1pu5zrc.mjs +1 -0
- package/website/dist/_worker.js/chunks/fortran-free-form_CSGOhJD6.mjs +1 -0
- package/website/dist/_worker.js/chunks/fsharp_B0xy-A4Y.mjs +1 -0
- package/website/dist/_worker.js/chunks/gdresource_CWppjlHq.mjs +1 -0
- package/website/dist/_worker.js/chunks/gdscript_eQCHchcS.mjs +1 -0
- package/website/dist/_worker.js/chunks/gdshader_C4kxepX7.mjs +1 -0
- package/website/dist/_worker.js/chunks/genie_ACtQLcDW.mjs +1 -0
- package/website/dist/_worker.js/chunks/gherkin_BFp2uKUd.mjs +1 -0
- package/website/dist/_worker.js/chunks/git-commit_CLg9ZwMV.mjs +1 -0
- package/website/dist/_worker.js/chunks/git-rebase_DG8A80Nt.mjs +1 -0
- package/website/dist/_worker.js/chunks/github-dark-default_BI0EP2Kv.mjs +1 -0
- package/website/dist/_worker.js/chunks/github-dark-dimmed_a_NIC0Xb.mjs +1 -0
- package/website/dist/_worker.js/chunks/github-dark-high-contrast_jZGqT7hk.mjs +1 -0
- package/website/dist/_worker.js/chunks/github-dark_CHCDNd2O.mjs +1 -0
- package/website/dist/_worker.js/chunks/github-light-default_DRbOW5RG.mjs +1 -0
- package/website/dist/_worker.js/chunks/github-light-high-contrast_tn_kWutM.mjs +1 -0
- package/website/dist/_worker.js/chunks/github-light_D9brYzot.mjs +1 -0
- package/website/dist/_worker.js/chunks/gleam_Dmhu1oxW.mjs +1 -0
- package/website/dist/_worker.js/chunks/glimmer-js_BfZbXy8A.mjs +1 -0
- package/website/dist/_worker.js/chunks/glimmer-ts_B9QVICrD.mjs +1 -0
- package/website/dist/_worker.js/chunks/glsl_DD2PPwOs.mjs +1 -0
- package/website/dist/_worker.js/chunks/gnuplot_D2OYChUX.mjs +1 -0
- package/website/dist/_worker.js/chunks/go_DYGFTe3h.mjs +1 -0
- package/website/dist/_worker.js/chunks/graphql_B7XsT3nH.mjs +1 -0
- package/website/dist/_worker.js/chunks/groovy_BO12Uwkl.mjs +1 -0
- package/website/dist/_worker.js/chunks/hack_CB2_ztCP.mjs +1 -0
- package/website/dist/_worker.js/chunks/haml_CyfDcDD3.mjs +1 -0
- package/website/dist/_worker.js/chunks/handlebars_CfpxpWm2.mjs +1 -0
- package/website/dist/_worker.js/chunks/haskell_jUeC5uN5.mjs +1 -0
- package/website/dist/_worker.js/chunks/haxe_B6GxP1WB.mjs +1 -0
- package/website/dist/_worker.js/chunks/hcl_DwoHV2oh.mjs +1 -0
- package/website/dist/_worker.js/chunks/hjson_DV7cJRk4.mjs +1 -0
- package/website/dist/_worker.js/chunks/hlsl_BlFCscPI.mjs +1 -0
- package/website/dist/_worker.js/chunks/houston_COBFG1Mx.mjs +1 -0
- package/website/dist/_worker.js/chunks/html-derivative_C9pJ337h.mjs +1 -0
- package/website/dist/_worker.js/chunks/html_D1OkrZS5.mjs +1 -0
- package/website/dist/_worker.js/chunks/http_DIGXRqvJ.mjs +1 -0
- package/website/dist/_worker.js/chunks/hxml_DEwh9i-c.mjs +1 -0
- package/website/dist/_worker.js/chunks/hy_DDoIgW1K.mjs +1 -0
- package/website/dist/_worker.js/chunks/imba_B00zbHo4.mjs +1 -0
- package/website/dist/_worker.js/chunks/index_C1UTDwYg.mjs +1861 -0
- package/website/dist/_worker.js/chunks/ini_D7XQA_p8.mjs +1 -0
- package/website/dist/_worker.js/chunks/java_B9wdFd8K.mjs +1 -0
- package/website/dist/_worker.js/chunks/javascript_CLsPGOON.mjs +1 -0
- package/website/dist/_worker.js/chunks/jinja_jarBCAN1.mjs +1 -0
- package/website/dist/_worker.js/chunks/jison_oGg3J708.mjs +1 -0
- package/website/dist/_worker.js/chunks/json5_DlZ1Kyaa.mjs +1 -0
- package/website/dist/_worker.js/chunks/json_DaYk_FMp.mjs +1 -0
- package/website/dist/_worker.js/chunks/jsonc_DlwgfSDs.mjs +1 -0
- package/website/dist/_worker.js/chunks/jsonl_BbCCVaZF.mjs +1 -0
- package/website/dist/_worker.js/chunks/jsonnet_Dt-G75xe.mjs +1 -0
- package/website/dist/_worker.js/chunks/jssm_BtKFTj2A.mjs +1 -0
- package/website/dist/_worker.js/chunks/jsx_DDx_xAZ8.mjs +1 -0
- package/website/dist/_worker.js/chunks/julia_CK0lv68l.mjs +1 -0
- package/website/dist/_worker.js/chunks/kanagawa-dragon_BldAK3Oo.mjs +1 -0
- package/website/dist/_worker.js/chunks/kanagawa-lotus_DVM8FX9_.mjs +1 -0
- package/website/dist/_worker.js/chunks/kanagawa-wave_Dpih0AKP.mjs +1 -0
- package/website/dist/_worker.js/chunks/kotlin_kWneB9V_.mjs +1 -0
- package/website/dist/_worker.js/chunks/kusto_BKVATd95.mjs +1 -0
- package/website/dist/_worker.js/chunks/laserwave_BqatxsVl.mjs +1 -0
- package/website/dist/_worker.js/chunks/latex_LVDcGBbc.mjs +1 -0
- package/website/dist/_worker.js/chunks/lean_W7qo-5M2.mjs +1 -0
- package/website/dist/_worker.js/chunks/less_DFNwJnBH.mjs +1 -0
- package/website/dist/_worker.js/chunks/light-plus_Dp0AoWsO.mjs +1 -0
- package/website/dist/_worker.js/chunks/liquid_D24qs0pc.mjs +1 -0
- package/website/dist/_worker.js/chunks/log_IPWMXriF.mjs +1 -0
- package/website/dist/_worker.js/chunks/logo_C6KaatrQ.mjs +1 -0
- package/website/dist/_worker.js/chunks/lua_CwnEf-T7.mjs +1 -0
- package/website/dist/_worker.js/chunks/luau_Br3-CXjS.mjs +1 -0
- package/website/dist/_worker.js/chunks/make_UBNG-kOo.mjs +1 -0
- package/website/dist/_worker.js/chunks/markdown_C7mhJFCm.mjs +1 -0
- package/website/dist/_worker.js/chunks/marko_4tchUvI7.mjs +1 -0
- package/website/dist/_worker.js/chunks/material-theme-darker_SKtaNEPn.mjs +1 -0
- package/website/dist/_worker.js/chunks/material-theme-lighter_zOX_DZCH.mjs +1 -0
- package/website/dist/_worker.js/chunks/material-theme-ocean_BN9WbhdC.mjs +1 -0
- package/website/dist/_worker.js/chunks/material-theme-palenight_DT_covjH.mjs +1 -0
- package/website/dist/_worker.js/chunks/material-theme_6RpeM3kc.mjs +1 -0
- package/website/dist/_worker.js/chunks/matlab_DCOXsPKR.mjs +1 -0
- package/website/dist/_worker.js/chunks/mdc_B9gb2UFP.mjs +1 -0
- package/website/dist/_worker.js/chunks/mdx_DGU7Nu9u.mjs +1 -0
- package/website/dist/_worker.js/chunks/mermaid_B69URzsZ.mjs +1 -0
- package/website/dist/_worker.js/chunks/min-dark_BgxifOMI.mjs +1 -0
- package/website/dist/_worker.js/chunks/min-light_BrPjXxUp.mjs +1 -0
- package/website/dist/_worker.js/chunks/mipsasm_9U-4_t7k.mjs +1 -0
- package/website/dist/_worker.js/chunks/mojo_B0wt7ug3.mjs +1 -0
- package/website/dist/_worker.js/chunks/monokai_B6Pxpoyi.mjs +1 -0
- package/website/dist/_worker.js/chunks/move_1eid4CyR.mjs +1 -0
- package/website/dist/_worker.js/chunks/narrat_Ds6-p5JZ.mjs +1 -0
- package/website/dist/_worker.js/chunks/nextflow_v2N1Qlqa.mjs +1 -0
- package/website/dist/_worker.js/chunks/nginx_Bp9Ab2NH.mjs +1 -0
- package/website/dist/_worker.js/chunks/night-owl_CdwOw_sc.mjs +1 -0
- package/website/dist/_worker.js/chunks/nim_BXGDUe53.mjs +1 -0
- package/website/dist/_worker.js/chunks/nix_CUig1nJH.mjs +1 -0
- package/website/dist/_worker.js/chunks/noop-middleware_DlWGj5t5.mjs +10 -0
- package/website/dist/_worker.js/chunks/nord_SPoG1iae.mjs +1 -0
- package/website/dist/_worker.js/chunks/nushell_DJw1Lca8.mjs +1 -0
- package/website/dist/_worker.js/chunks/objective-c_Bktzl_CO.mjs +1 -0
- package/website/dist/_worker.js/chunks/objective-cpp_CP4DWdDp.mjs +1 -0
- package/website/dist/_worker.js/chunks/ocaml_CeEAs7bZ.mjs +1 -0
- package/website/dist/_worker.js/chunks/one-dark-pro_-hIwCNMi.mjs +1 -0
- package/website/dist/_worker.js/chunks/one-light_DSmYvJ05.mjs +1 -0
- package/website/dist/_worker.js/chunks/pascal_C-S_Ms_o.mjs +1 -0
- package/website/dist/_worker.js/chunks/perl_CKamvo15.mjs +1 -0
- package/website/dist/_worker.js/chunks/php_BlmcX_F3.mjs +1 -0
- package/website/dist/_worker.js/chunks/plastic_Ryt8tVoA.mjs +1 -0
- package/website/dist/_worker.js/chunks/plsql_Cb3v7cBj.mjs +1 -0
- package/website/dist/_worker.js/chunks/po_DZbdNRlo.mjs +1 -0
- package/website/dist/_worker.js/chunks/poimandres_bYmE3_5d.mjs +1 -0
- package/website/dist/_worker.js/chunks/polar_pJkMGwoW.mjs +1 -0
- package/website/dist/_worker.js/chunks/postcss_BAXSOKgk.mjs +1 -0
- package/website/dist/_worker.js/chunks/powerquery_oITMGN4x.mjs +1 -0
- package/website/dist/_worker.js/chunks/powershell_6306-xIF.mjs +1 -0
- package/website/dist/_worker.js/chunks/prisma_DSDxnZGz.mjs +1 -0
- package/website/dist/_worker.js/chunks/prolog_CxG7tjZR.mjs +1 -0
- package/website/dist/_worker.js/chunks/proto_CS9ByXm1.mjs +1 -0
- package/website/dist/_worker.js/chunks/pug_BMtLJo6U.mjs +1 -0
- package/website/dist/_worker.js/chunks/puppet_BfeeSzee.mjs +1 -0
- package/website/dist/_worker.js/chunks/purescript_BFfueNaH.mjs +1 -0
- package/website/dist/_worker.js/chunks/python_Cc4Faapv.mjs +1 -0
- package/website/dist/_worker.js/chunks/qml_C1CTJTK8.mjs +1 -0
- package/website/dist/_worker.js/chunks/qmldir_nG1KaqKR.mjs +1 -0
- package/website/dist/_worker.js/chunks/qss_Cncxk263.mjs +1 -0
- package/website/dist/_worker.js/chunks/r_ChR54Ihi.mjs +1 -0
- package/website/dist/_worker.js/chunks/racket_BDrhptDs.mjs +1 -0
- package/website/dist/_worker.js/chunks/raku_07OUHa0P.mjs +1 -0
- package/website/dist/_worker.js/chunks/razor_DIP3INLa.mjs +1 -0
- package/website/dist/_worker.js/chunks/red_DOPXfj-6.mjs +1 -0
- package/website/dist/_worker.js/chunks/reg_B64SwEDj.mjs +1 -0
- package/website/dist/_worker.js/chunks/regexp_ButFGoB5.mjs +1 -0
- package/website/dist/_worker.js/chunks/rel_BWJAWqZD.mjs +1 -0
- package/website/dist/_worker.js/chunks/riscv_79gXlbsF.mjs +1 -0
- package/website/dist/_worker.js/chunks/rose-pine-dawn_DHIjVGd3.mjs +1 -0
- package/website/dist/_worker.js/chunks/rose-pine-moon_t86aEbs0.mjs +1 -0
- package/website/dist/_worker.js/chunks/rose-pine_BHgrcDCs.mjs +1 -0
- package/website/dist/_worker.js/chunks/rst_D3F4Fcpj.mjs +1 -0
- package/website/dist/_worker.js/chunks/ruby_Cs7vM9iv.mjs +1 -0
- package/website/dist/_worker.js/chunks/rust_DpyRVatH.mjs +1 -0
- package/website/dist/_worker.js/chunks/sas_DW45xZXN.mjs +1 -0
- package/website/dist/_worker.js/chunks/sass_C6SiMwN_.mjs +1 -0
- package/website/dist/_worker.js/chunks/scala_DlZOjNZk.mjs +1 -0
- package/website/dist/_worker.js/chunks/scheme_D2ezSJXu.mjs +1 -0
- package/website/dist/_worker.js/chunks/scss_DG5Spjqu.mjs +1 -0
- package/website/dist/_worker.js/chunks/sdbl_ZCYaj4VN.mjs +1 -0
- package/website/dist/_worker.js/chunks/shaderlab_CAcRkg1_.mjs +1 -0
- package/website/dist/_worker.js/chunks/shellscript_BWwhkDVh.mjs +1 -0
- package/website/dist/_worker.js/chunks/shellsession_BfEA3juK.mjs +1 -0
- package/website/dist/_worker.js/chunks/slack-dark_CL3lSpCc.mjs +1 -0
- package/website/dist/_worker.js/chunks/slack-ochin_DdZKOQVh.mjs +1 -0
- package/website/dist/_worker.js/chunks/smalltalk_DgilzSui.mjs +1 -0
- package/website/dist/_worker.js/chunks/snazzy-light_eJU08Pz_.mjs +1 -0
- package/website/dist/_worker.js/chunks/solarized-dark_Dg_YQywx.mjs +1 -0
- package/website/dist/_worker.js/chunks/solarized-light_BnIsrA6p.mjs +1 -0
- package/website/dist/_worker.js/chunks/solidity_DkseH8pQ.mjs +1 -0
- package/website/dist/_worker.js/chunks/soy_DU7bOYoG.mjs +1 -0
- package/website/dist/_worker.js/chunks/sparql_BuI1DBDH.mjs +1 -0
- package/website/dist/_worker.js/chunks/splunk_B8Ha9Pkg.mjs +1 -0
- package/website/dist/_worker.js/chunks/sql_BniHwea5.mjs +1 -0
- package/website/dist/_worker.js/chunks/ssh-config_CkE1GuVe.mjs +1 -0
- package/website/dist/_worker.js/chunks/stata_Dtqpbd_l.mjs +1 -0
- package/website/dist/_worker.js/chunks/stylus_CXTtglzO.mjs +1 -0
- package/website/dist/_worker.js/chunks/svelte_BjWYcUCN.mjs +1 -0
- package/website/dist/_worker.js/chunks/swift_BzHql_rM.mjs +1 -0
- package/website/dist/_worker.js/chunks/synthwave-84_DLRNhxNA.mjs +1 -0
- package/website/dist/_worker.js/chunks/system-verilog_ChyInPph.mjs +1 -0
- package/website/dist/_worker.js/chunks/systemd_Bi9Qa2qD.mjs +1 -0
- package/website/dist/_worker.js/chunks/talonscript_B3sH_Y-V.mjs +1 -0
- package/website/dist/_worker.js/chunks/tasl_BJ5yipRs.mjs +1 -0
- package/website/dist/_worker.js/chunks/tcl_CoJQjNoP.mjs +1 -0
- package/website/dist/_worker.js/chunks/templ_CrU7Ffil.mjs +1 -0
- package/website/dist/_worker.js/chunks/terraform_DT9JSFpC.mjs +1 -0
- package/website/dist/_worker.js/chunks/tex_5PKu2yA0.mjs +1 -0
- package/website/dist/_worker.js/chunks/tokyo-night_Buo8OK7-.mjs +1 -0
- package/website/dist/_worker.js/chunks/toml_CPuXX3oc.mjs +1 -0
- package/website/dist/_worker.js/chunks/ts-tags_D0M_1VSH.mjs +1 -0
- package/website/dist/_worker.js/chunks/tsv_CuivVNot.mjs +1 -0
- package/website/dist/_worker.js/chunks/tsx_MkuGr8MY.mjs +1 -0
- package/website/dist/_worker.js/chunks/turtle_BqgEPK7f.mjs +1 -0
- package/website/dist/_worker.js/chunks/twig_r1G9rpYJ.mjs +1 -0
- package/website/dist/_worker.js/chunks/typescript_Au5buqzM.mjs +1 -0
- package/website/dist/_worker.js/chunks/typespec_47rhBK_z.mjs +1 -0
- package/website/dist/_worker.js/chunks/typst_BAtuQLh-.mjs +1 -0
- package/website/dist/_worker.js/chunks/v_BIvWImHg.mjs +1 -0
- package/website/dist/_worker.js/chunks/vala_DYEacj30.mjs +1 -0
- package/website/dist/_worker.js/chunks/vb_CikQuqGJ.mjs +1 -0
- package/website/dist/_worker.js/chunks/verilog_BQRENwI-.mjs +1 -0
- package/website/dist/_worker.js/chunks/vesper_DA0kvTmj.mjs +1 -0
- package/website/dist/_worker.js/chunks/vhdl_DHscJIyg.mjs +1 -0
- package/website/dist/_worker.js/chunks/viml_F2pvMwvG.mjs +1 -0
- package/website/dist/_worker.js/chunks/vitesse-black_D9tjNzd0.mjs +1 -0
- package/website/dist/_worker.js/chunks/vitesse-dark_Bnm5d0hd.mjs +1 -0
- package/website/dist/_worker.js/chunks/vitesse-light_CHwbyjNR.mjs +1 -0
- package/website/dist/_worker.js/chunks/vue-html_DyYtbbMK.mjs +1 -0
- package/website/dist/_worker.js/chunks/vue_DofN6juy.mjs +1 -0
- package/website/dist/_worker.js/chunks/vyper_CiR0m-OV.mjs +1 -0
- package/website/dist/_worker.js/chunks/wasm_CwIGgRGf.mjs +1 -0
- package/website/dist/_worker.js/chunks/wasm_jKWhg0J0.mjs +1 -0
- package/website/dist/_worker.js/chunks/wenyan_DKvVZKXW.mjs +1 -0
- package/website/dist/_worker.js/chunks/wgsl_BOWZY7yw.mjs +1 -0
- package/website/dist/_worker.js/chunks/wikitext_CXDhhHPy.mjs +1 -0
- package/website/dist/_worker.js/chunks/wolfram_ChkmGnW0.mjs +1 -0
- package/website/dist/_worker.js/chunks/xml_DXH3hHIu.mjs +1 -0
- package/website/dist/_worker.js/chunks/xsl_DuP2mFjg.mjs +1 -0
- package/website/dist/_worker.js/chunks/yaml_IGiEkTge.mjs +1 -0
- package/website/dist/_worker.js/chunks/zenscript_59iXGyNw.mjs +1 -0
- package/website/dist/_worker.js/chunks/zig_DKzb0zdT.mjs +1 -0
- package/website/dist/_worker.js/index.js +53 -0
- package/website/dist/_worker.js/manifest_BAAoOzaU.mjs +98 -0
- package/website/dist/_worker.js/pages/_image.astro.mjs +24 -0
- package/website/dist/_worker.js/pages/agents.astro.mjs +1 -0
- package/website/dist/_worker.js/pages/animation.astro.mjs +1 -0
- package/website/dist/_worker.js/pages/api/raw-markdown/_---path_.astro.mjs +44 -0
- package/website/dist/_worker.js/pages/config.astro.mjs +1 -0
- package/website/dist/_worker.js/pages/fonts.astro.mjs +1 -0
- package/website/dist/_worker.js/pages/getting-started.astro.mjs +1 -0
- package/website/dist/_worker.js/pages/helpers.astro.mjs +1 -0
- package/website/dist/_worker.js/pages/images.astro.mjs +1 -0
- package/website/dist/_worker.js/pages/index.astro.mjs +1 -0
- package/website/dist/_worker.js/pages/llm.txt.astro.mjs +1 -0
- package/website/dist/_worker.js/pages/preview.astro.mjs +1 -0
- package/website/dist/_worker.js/pages/sdk.astro.mjs +1 -0
- package/website/dist/_worker.js/pages/sitemap.xml.astro.mjs +1 -0
- package/website/dist/_worker.js/pages/styling.astro.mjs +1 -0
- package/website/dist/_worker.js/pages/templates.astro.mjs +1 -0
- package/website/dist/_worker.js/pages/video.astro.mjs +1 -0
- package/website/dist/_worker.js/renderers.mjs +57 -0
- package/website/dist/agents/index.html +3 -2
- package/website/dist/animation/index.html +402 -128
- package/website/dist/config/index.html +184 -0
- package/website/dist/fonts/index.html +56 -52
- package/website/dist/getting-started/index.html +107 -0
- package/website/dist/helpers/index.html +8 -8
- package/website/dist/images/index.html +50 -23
- package/website/dist/index.html +114 -148
- package/website/dist/llm.txt +751 -1055
- package/website/dist/preview/index.html +111 -0
- package/website/dist/robots.txt +35 -0
- package/website/dist/sdk/index.html +390 -52
- package/website/dist/sitemap.xml +76 -0
- package/website/dist/styling/index.html +10 -7
- package/website/dist/templates/index.html +11 -59
- package/website/dist/video/index.html +106 -537
- package/website/package.json +1 -0
- package/website/public/.assetsignore +3 -0
- package/website/templates/og-image.tsx +61 -0
- package/website/wrangler.toml +12 -0
- package/website/dist/_astro/agents.I1-fN38o.css +0 -1
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test suite for user-generated templates
|
|
3
|
+
* - defineTemplateFromSource (code editor)
|
|
4
|
+
* - defineTemplateFromSchema (visual builder)
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { defineTemplateFromSource, defineTemplateFromSchema, renderImage, renderVideo } from './dist/sdk/index.js';
|
|
8
|
+
import React from 'react';
|
|
9
|
+
import fs from 'fs/promises';
|
|
10
|
+
|
|
11
|
+
const h = React.createElement;
|
|
12
|
+
let passed = 0;
|
|
13
|
+
let failed = 0;
|
|
14
|
+
|
|
15
|
+
function test(name, fn) {
|
|
16
|
+
try {
|
|
17
|
+
fn();
|
|
18
|
+
console.log(`✓ ${name}`);
|
|
19
|
+
passed++;
|
|
20
|
+
} catch (error) {
|
|
21
|
+
console.error(`✗ ${name}`);
|
|
22
|
+
console.error(` ${error.message}`);
|
|
23
|
+
failed++;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function asyncTest(name, fn) {
|
|
28
|
+
try {
|
|
29
|
+
await fn();
|
|
30
|
+
console.log(`✓ ${name}`);
|
|
31
|
+
passed++;
|
|
32
|
+
} catch (error) {
|
|
33
|
+
console.error(`✗ ${name}`);
|
|
34
|
+
console.error(` ${error.message}`);
|
|
35
|
+
failed++;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
console.log('Testing defineTemplateFromSource\n');
|
|
40
|
+
|
|
41
|
+
// Test 1: Basic source template
|
|
42
|
+
await asyncTest('Source: Basic image template', async () => {
|
|
43
|
+
const source = `
|
|
44
|
+
export const meta = {
|
|
45
|
+
name: 'test',
|
|
46
|
+
type: 'image',
|
|
47
|
+
size: { width: 100, height: 100 }
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export default ({ tw }) => {
|
|
51
|
+
const h = React.createElement;
|
|
52
|
+
return h('div', { style: tw('bg-blue-500 w-full h-full') });
|
|
53
|
+
};
|
|
54
|
+
`;
|
|
55
|
+
|
|
56
|
+
const template = defineTemplateFromSource(source);
|
|
57
|
+
if (template.name !== 'test') throw new Error('Template name incorrect');
|
|
58
|
+
if (template.type !== 'image') throw new Error('Template type incorrect');
|
|
59
|
+
|
|
60
|
+
const png = await renderImage(template, {});
|
|
61
|
+
if (!Buffer.isBuffer(png)) throw new Error('Should return buffer');
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// Test 2: Source template with props
|
|
65
|
+
await asyncTest('Source: Template with props', async () => {
|
|
66
|
+
const source = `
|
|
67
|
+
export const meta = {
|
|
68
|
+
name: 'with-props',
|
|
69
|
+
type: 'image',
|
|
70
|
+
size: { width: 200, height: 100 }
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export default ({ tw, title }) => {
|
|
74
|
+
const h = React.createElement;
|
|
75
|
+
return h('div', { style: tw('flex flex-col bg-white p-4') },
|
|
76
|
+
h('h1', { style: tw('text-black') }, title)
|
|
77
|
+
);
|
|
78
|
+
};
|
|
79
|
+
`;
|
|
80
|
+
|
|
81
|
+
const template = defineTemplateFromSource(source);
|
|
82
|
+
const png = await renderImage(template, { title: 'Hello' });
|
|
83
|
+
if (!Buffer.isBuffer(png)) throw new Error('Should return buffer');
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Test 3: Source template with config
|
|
87
|
+
await asyncTest('Source: Template with config', async () => {
|
|
88
|
+
const source = `
|
|
89
|
+
export const meta = {
|
|
90
|
+
name: 'with-config',
|
|
91
|
+
type: 'image',
|
|
92
|
+
size: { width: 200, height: 100 }
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export default ({ tw }) => {
|
|
96
|
+
const h = React.createElement;
|
|
97
|
+
return h('div', { style: tw('bg-primary p-4') });
|
|
98
|
+
};
|
|
99
|
+
`;
|
|
100
|
+
|
|
101
|
+
const template = defineTemplateFromSource(source, {
|
|
102
|
+
config: {
|
|
103
|
+
colors: { primary: '#ff0000' },
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
const svg = await renderImage(template, {}, { format: 'svg' });
|
|
108
|
+
const svgStr = svg.toString();
|
|
109
|
+
if (!svgStr.includes('#ff0000')) throw new Error('Config colors not applied');
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// Test 4: Source video template
|
|
113
|
+
await asyncTest('Source: Video template', async () => {
|
|
114
|
+
const source = `
|
|
115
|
+
export const meta = {
|
|
116
|
+
name: 'video-test',
|
|
117
|
+
type: 'video',
|
|
118
|
+
size: { width: 100, height: 100 },
|
|
119
|
+
video: { fps: 2, duration: 0.5 }
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
export default ({ tw }) => {
|
|
123
|
+
const h = React.createElement;
|
|
124
|
+
return h('div', {
|
|
125
|
+
style: tw('bg-blue-500 w-full h-full enter-fade-in/0/500')
|
|
126
|
+
});
|
|
127
|
+
};
|
|
128
|
+
`;
|
|
129
|
+
|
|
130
|
+
const template = defineTemplateFromSource(source);
|
|
131
|
+
if (template.type !== 'video') throw new Error('Should be video type');
|
|
132
|
+
|
|
133
|
+
const mp4 = await renderVideo(template, {});
|
|
134
|
+
if (!Buffer.isBuffer(mp4)) throw new Error('Should return buffer');
|
|
135
|
+
if (mp4.length === 0) throw new Error('Video should have content');
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// Test 5: Invalid source - no meta
|
|
139
|
+
test('Source: Error on missing meta', () => {
|
|
140
|
+
const source = `
|
|
141
|
+
export default () => {
|
|
142
|
+
return React.createElement('div', {}, 'test');
|
|
143
|
+
};
|
|
144
|
+
`;
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
defineTemplateFromSource(source);
|
|
148
|
+
throw new Error('Should have thrown error');
|
|
149
|
+
} catch (error) {
|
|
150
|
+
if (!error.message.includes('meta')) throw new Error('Should mention meta');
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// Test 6: Invalid source - no default export
|
|
155
|
+
test('Source: Error on missing default export', () => {
|
|
156
|
+
const source = `
|
|
157
|
+
export const meta = {
|
|
158
|
+
name: 'test',
|
|
159
|
+
size: { width: 100, height: 100 }
|
|
160
|
+
};
|
|
161
|
+
`;
|
|
162
|
+
|
|
163
|
+
try {
|
|
164
|
+
defineTemplateFromSource(source);
|
|
165
|
+
throw new Error('Should have thrown error');
|
|
166
|
+
} catch (error) {
|
|
167
|
+
if (!error.message.includes('default')) throw new Error('Should mention default export');
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
console.log('\nTesting defineTemplateFromSchema\n');
|
|
172
|
+
|
|
173
|
+
// Test 7: Basic schema template
|
|
174
|
+
await asyncTest('Schema: Basic template', async () => {
|
|
175
|
+
const schema = {
|
|
176
|
+
name: 'basic-schema',
|
|
177
|
+
size: { width: 200, height: 100 },
|
|
178
|
+
elements: [
|
|
179
|
+
{
|
|
180
|
+
type: 'div',
|
|
181
|
+
className: 'bg-blue-500 w-full h-full',
|
|
182
|
+
},
|
|
183
|
+
],
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
const template = defineTemplateFromSchema(schema);
|
|
187
|
+
if (template.name !== 'basic-schema') throw new Error('Name incorrect');
|
|
188
|
+
|
|
189
|
+
const png = await renderImage(template, {});
|
|
190
|
+
if (!Buffer.isBuffer(png)) throw new Error('Should return buffer');
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
// Test 8: Schema with text interpolation
|
|
194
|
+
await asyncTest('Schema: Text interpolation', async () => {
|
|
195
|
+
const schema = {
|
|
196
|
+
name: 'with-text',
|
|
197
|
+
size: { width: 300, height: 150 },
|
|
198
|
+
elements: [
|
|
199
|
+
{
|
|
200
|
+
type: 'div',
|
|
201
|
+
className: 'flex flex-col bg-white p-4 w-full h-full',
|
|
202
|
+
children: [
|
|
203
|
+
{
|
|
204
|
+
type: 'h1',
|
|
205
|
+
className: 'text-black',
|
|
206
|
+
content: '{{title}}',
|
|
207
|
+
},
|
|
208
|
+
],
|
|
209
|
+
},
|
|
210
|
+
],
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
const template = defineTemplateFromSchema(schema);
|
|
214
|
+
const svg = await renderImage(template, { title: 'Test Title' }, { format: 'svg' });
|
|
215
|
+
// SVG renders text as paths, so we can't check for literal strings
|
|
216
|
+
// Just verify it renders without error and has content
|
|
217
|
+
if (!Buffer.isBuffer(svg)) throw new Error('Should return buffer');
|
|
218
|
+
if (svg.length === 0) throw new Error('Should have content');
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
// Test 9: Schema with nested children
|
|
222
|
+
await asyncTest('Schema: Nested elements', async () => {
|
|
223
|
+
const schema = {
|
|
224
|
+
name: 'nested',
|
|
225
|
+
size: { width: 400, height: 200 },
|
|
226
|
+
elements: [
|
|
227
|
+
{
|
|
228
|
+
type: 'div',
|
|
229
|
+
className: 'flex flex-col w-full h-full bg-white p-4',
|
|
230
|
+
children: [
|
|
231
|
+
{
|
|
232
|
+
type: 'h1',
|
|
233
|
+
className: 'text-2xl font-bold',
|
|
234
|
+
content: '{{title}}',
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
type: 'p',
|
|
238
|
+
className: 'text-base',
|
|
239
|
+
content: '{{description}}',
|
|
240
|
+
},
|
|
241
|
+
],
|
|
242
|
+
},
|
|
243
|
+
],
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
const template = defineTemplateFromSchema(schema);
|
|
247
|
+
const svg = await renderImage(
|
|
248
|
+
template,
|
|
249
|
+
{ title: 'Nested', description: 'Works!' },
|
|
250
|
+
{ format: 'svg' }
|
|
251
|
+
);
|
|
252
|
+
// SVG renders text as paths, just verify it has content
|
|
253
|
+
if (!Buffer.isBuffer(svg)) throw new Error('Should return buffer');
|
|
254
|
+
if (svg.length === 0) throw new Error('Should have content');
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
// Test 10: Schema with config
|
|
258
|
+
await asyncTest('Schema: With config', async () => {
|
|
259
|
+
const schema = {
|
|
260
|
+
name: 'with-config',
|
|
261
|
+
size: { width: 200, height: 100 },
|
|
262
|
+
config: {
|
|
263
|
+
colors: {
|
|
264
|
+
primary: '#00ff00',
|
|
265
|
+
background: '#ffffff',
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
elements: [
|
|
269
|
+
{
|
|
270
|
+
type: 'div',
|
|
271
|
+
className: 'bg-primary w-full h-full',
|
|
272
|
+
},
|
|
273
|
+
],
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
const template = defineTemplateFromSchema(schema);
|
|
277
|
+
const svg = await renderImage(template, {}, { format: 'svg' });
|
|
278
|
+
const svgStr = svg.toString();
|
|
279
|
+
if (!svgStr.includes('#00ff00')) throw new Error('Primary color not applied');
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
// Test 11: Schema with multiple root elements
|
|
283
|
+
await asyncTest('Schema: Multiple root elements', async () => {
|
|
284
|
+
const schema = {
|
|
285
|
+
name: 'multi-root',
|
|
286
|
+
size: { width: 400, height: 200 },
|
|
287
|
+
elements: [
|
|
288
|
+
{
|
|
289
|
+
type: 'div',
|
|
290
|
+
className: 'flex w-full h-full bg-white',
|
|
291
|
+
children: [
|
|
292
|
+
{
|
|
293
|
+
type: 'div',
|
|
294
|
+
className: 'flex-1 bg-red-500',
|
|
295
|
+
content: 'First',
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
type: 'div',
|
|
299
|
+
className: 'flex-1 bg-blue-500',
|
|
300
|
+
content: 'Second',
|
|
301
|
+
},
|
|
302
|
+
],
|
|
303
|
+
},
|
|
304
|
+
],
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
const template = defineTemplateFromSchema(schema);
|
|
308
|
+
const svg = await renderImage(template, {}, { format: 'svg' });
|
|
309
|
+
// SVG renders text as paths, just verify it has content
|
|
310
|
+
if (!Buffer.isBuffer(svg)) throw new Error('Should return buffer');
|
|
311
|
+
if (svg.length === 0) throw new Error('Should have content');
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
// Test 12: Schema video template
|
|
315
|
+
await asyncTest('Schema: Video template', async () => {
|
|
316
|
+
const schema = {
|
|
317
|
+
name: 'video-schema',
|
|
318
|
+
type: 'video',
|
|
319
|
+
size: { width: 100, height: 100 },
|
|
320
|
+
video: { fps: 2, duration: 0.5 },
|
|
321
|
+
elements: [
|
|
322
|
+
{
|
|
323
|
+
type: 'div',
|
|
324
|
+
className: 'bg-purple-500 w-full h-full',
|
|
325
|
+
},
|
|
326
|
+
],
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
const template = defineTemplateFromSchema(schema);
|
|
330
|
+
if (template.type !== 'video') throw new Error('Should be video type');
|
|
331
|
+
|
|
332
|
+
const mp4 = await renderVideo(template, {});
|
|
333
|
+
if (!Buffer.isBuffer(mp4)) throw new Error('Should return buffer');
|
|
334
|
+
if (mp4.length === 0) throw new Error('Video should have content');
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
// Test 13: Schema with img element
|
|
338
|
+
await asyncTest('Schema: Image element with interpolation', async () => {
|
|
339
|
+
const schema = {
|
|
340
|
+
name: 'with-image',
|
|
341
|
+
size: { width: 400, height: 200 },
|
|
342
|
+
elements: [
|
|
343
|
+
{
|
|
344
|
+
type: 'div',
|
|
345
|
+
className: 'bg-white w-full h-full flex items-center justify-center',
|
|
346
|
+
children: [
|
|
347
|
+
{
|
|
348
|
+
type: 'img',
|
|
349
|
+
src: '{{imageUrl}}',
|
|
350
|
+
style: { width: '128px', height: '128px' },
|
|
351
|
+
},
|
|
352
|
+
],
|
|
353
|
+
},
|
|
354
|
+
],
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
const template = defineTemplateFromSchema(schema);
|
|
358
|
+
// Use a minimal valid 1x1 red PNG
|
|
359
|
+
const redPixel = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==';
|
|
360
|
+
const svg = await renderImage(
|
|
361
|
+
template,
|
|
362
|
+
{ imageUrl: redPixel },
|
|
363
|
+
{ format: 'svg' }
|
|
364
|
+
);
|
|
365
|
+
const svgStr = svg.toString();
|
|
366
|
+
if (!svgStr.includes('data:image/png')) throw new Error('Image src not interpolated');
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
// Test 14: Schema error - empty elements
|
|
370
|
+
test('Schema: Error on empty elements', () => {
|
|
371
|
+
const schema = {
|
|
372
|
+
name: 'empty',
|
|
373
|
+
size: { width: 100, height: 100 },
|
|
374
|
+
elements: [],
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
try {
|
|
378
|
+
const template = defineTemplateFromSchema(schema);
|
|
379
|
+
// Try to render - should fail
|
|
380
|
+
renderImage(template, {});
|
|
381
|
+
throw new Error('Should have thrown error');
|
|
382
|
+
} catch (error) {
|
|
383
|
+
if (!error.message.includes('element')) throw new Error('Should mention elements');
|
|
384
|
+
}
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
// Test 15: Complex real-world schema
|
|
388
|
+
await asyncTest('Schema: Complex real-world example', async () => {
|
|
389
|
+
const schema = {
|
|
390
|
+
name: 'og-card',
|
|
391
|
+
size: { width: 1200, height: 630 },
|
|
392
|
+
config: {
|
|
393
|
+
colors: {
|
|
394
|
+
primary: '#3b82f6',
|
|
395
|
+
secondary: '#8b5cf6',
|
|
396
|
+
background: '#ffffff',
|
|
397
|
+
text: '#1f2937',
|
|
398
|
+
},
|
|
399
|
+
},
|
|
400
|
+
elements: [
|
|
401
|
+
{
|
|
402
|
+
type: 'div',
|
|
403
|
+
className: 'flex w-full h-full bg-background',
|
|
404
|
+
children: [
|
|
405
|
+
{
|
|
406
|
+
type: 'div',
|
|
407
|
+
className: 'flex flex-col w-1/3 bg-primary p-8 justify-between',
|
|
408
|
+
children: [
|
|
409
|
+
{
|
|
410
|
+
type: 'h2',
|
|
411
|
+
className: 'text-2xl font-bold text-white',
|
|
412
|
+
content: '{{category}}',
|
|
413
|
+
},
|
|
414
|
+
{
|
|
415
|
+
type: 'p',
|
|
416
|
+
className: 'text-white/80',
|
|
417
|
+
content: '{{date}}',
|
|
418
|
+
},
|
|
419
|
+
],
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
type: 'div',
|
|
423
|
+
className: 'flex flex-col flex-1 p-12 justify-center',
|
|
424
|
+
children: [
|
|
425
|
+
{
|
|
426
|
+
type: 'h1',
|
|
427
|
+
className: 'text-6xl font-bold text-text mb-4',
|
|
428
|
+
content: '{{title}}',
|
|
429
|
+
},
|
|
430
|
+
{
|
|
431
|
+
type: 'div',
|
|
432
|
+
className: 'w-24 h-2 bg-secondary mb-4',
|
|
433
|
+
},
|
|
434
|
+
{
|
|
435
|
+
type: 'p',
|
|
436
|
+
className: 'text-2xl text-text/70',
|
|
437
|
+
content: '{{description}}',
|
|
438
|
+
},
|
|
439
|
+
],
|
|
440
|
+
},
|
|
441
|
+
],
|
|
442
|
+
},
|
|
443
|
+
],
|
|
444
|
+
};
|
|
445
|
+
|
|
446
|
+
const template = defineTemplateFromSchema(schema);
|
|
447
|
+
const png = await renderImage(template, {
|
|
448
|
+
category: 'TECHNOLOGY',
|
|
449
|
+
date: 'March 2024',
|
|
450
|
+
title: 'The Future of AI',
|
|
451
|
+
description: 'Exploring next-generation artificial intelligence',
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
if (!Buffer.isBuffer(png)) throw new Error('Should return buffer');
|
|
455
|
+
if (png.length === 0) throw new Error('Image should have content');
|
|
456
|
+
|
|
457
|
+
// Save for visual inspection
|
|
458
|
+
await fs.writeFile('test-complex-schema.png', png);
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
// Summary
|
|
462
|
+
console.log('\n' + '='.repeat(50));
|
|
463
|
+
console.log(`Tests passed: ${passed}`);
|
|
464
|
+
console.log(`Tests failed: ${failed}`);
|
|
465
|
+
console.log('='.repeat(50));
|
|
466
|
+
|
|
467
|
+
if (failed > 0) {
|
|
468
|
+
process.exit(1);
|
|
469
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import '@inox-tools/astro-when';
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# Deployment Guide
|
|
2
|
+
|
|
3
|
+
This documentation website is configured for deployment on **Cloudflare Pages/Workers** with hybrid rendering.
|
|
4
|
+
|
|
5
|
+
## Quick Deploy
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
cd website
|
|
9
|
+
|
|
10
|
+
# Install dependencies
|
|
11
|
+
npm install
|
|
12
|
+
|
|
13
|
+
# Build and deploy
|
|
14
|
+
npm run deploy
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## What's Included
|
|
18
|
+
|
|
19
|
+
### 1. Dynamic OG Image Generation
|
|
20
|
+
|
|
21
|
+
Every documentation page automatically generates its own Open Graph image using **loopwind SDK**.
|
|
22
|
+
|
|
23
|
+
- **API Route**: `/api/og/[...slug].tsx`
|
|
24
|
+
- **Format**: 1200x630 PNG
|
|
25
|
+
- **Generation**: Pre-rendered at build time for known pages, generated on-demand for others
|
|
26
|
+
- **Caching**: Immutable cache headers for optimal performance
|
|
27
|
+
|
|
28
|
+
**Example URLs:**
|
|
29
|
+
- `/api/og/sdk` → SDK page OG image
|
|
30
|
+
- `/api/og/config` → Config page OG image
|
|
31
|
+
- `/api/og/getting-started` → Getting Started OG image
|
|
32
|
+
|
|
33
|
+
### 2. Cloudflare Workers Adapter
|
|
34
|
+
|
|
35
|
+
- **File**: `astro.config.mjs`
|
|
36
|
+
- **Adapter**: `@astrojs/cloudflare`
|
|
37
|
+
- **Output**: Hybrid (SSG + SSR)
|
|
38
|
+
- **Platform**: Cloudflare Workers with Assets
|
|
39
|
+
|
|
40
|
+
### 3. Build Configuration
|
|
41
|
+
|
|
42
|
+
The Vite config externalizes Node.js built-ins for Cloudflare compatibility:
|
|
43
|
+
|
|
44
|
+
```javascript
|
|
45
|
+
vite: {
|
|
46
|
+
ssr: {
|
|
47
|
+
external: ['node:fs', 'fs', 'path', etc.],
|
|
48
|
+
noExternal: ['loopwind'], // Bundle loopwind SDK
|
|
49
|
+
},
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Deployment Steps
|
|
54
|
+
|
|
55
|
+
### First Time Setup
|
|
56
|
+
|
|
57
|
+
1. **Install Wrangler CLI** (if not already installed):
|
|
58
|
+
```bash
|
|
59
|
+
npm install -g wrangler
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
2. **Login to Cloudflare**:
|
|
63
|
+
```bash
|
|
64
|
+
npx wrangler login
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
3. **Build and Deploy**:
|
|
68
|
+
```bash
|
|
69
|
+
npm run deploy
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Subsequent Deployments
|
|
73
|
+
|
|
74
|
+
Just run:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
npm run deploy
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Or separately:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
npm run build
|
|
84
|
+
npm run cf:deploy
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Environment
|
|
88
|
+
|
|
89
|
+
- **Node.js**: 18+ recommended
|
|
90
|
+
- **Package Manager**: npm
|
|
91
|
+
- **Platform**: Cloudflare Workers + Assets
|
|
92
|
+
- **Build Time**: ~2-3 seconds
|
|
93
|
+
|
|
94
|
+
## Performance
|
|
95
|
+
|
|
96
|
+
- **Build**: ~2.7s
|
|
97
|
+
- **OG Images**: Generated at build time (< 100ms each)
|
|
98
|
+
- **Caching**: Immutable cache headers for all OG images
|
|
99
|
+
- **CDN**: Cloudflare's global network
|
|
100
|
+
|
|
101
|
+
## Verify Deployment
|
|
102
|
+
|
|
103
|
+
After deployment, test:
|
|
104
|
+
|
|
105
|
+
1. **Home page**: `https://your-domain.com`
|
|
106
|
+
2. **OG image**: `https://your-domain.com/api/og/sdk`
|
|
107
|
+
3. **API routes**: All `/api/*` routes should work
|
|
108
|
+
|
|
109
|
+
## Troubleshooting
|
|
110
|
+
|
|
111
|
+
### Build Fails
|
|
112
|
+
|
|
113
|
+
- Check Node.js version (18+)
|
|
114
|
+
- Run `npm install` to ensure dependencies are up to date
|
|
115
|
+
- Check `npm run build` output for errors
|
|
116
|
+
|
|
117
|
+
### OG Images Not Generating
|
|
118
|
+
|
|
119
|
+
- Verify loopwind is installed: `npm list loopwind`
|
|
120
|
+
- Check `/api/og/[...slug].tsx` is present
|
|
121
|
+
- Test locally: `npm run dev` then visit `http://localhost:4321/api/og/sdk`
|
|
122
|
+
|
|
123
|
+
### Cloudflare Deploy Fails
|
|
124
|
+
|
|
125
|
+
- Ensure you're logged in: `npx wrangler whoami`
|
|
126
|
+
- Check `wrangler.toml` configuration (should not exist for Pages)
|
|
127
|
+
- Verify Cloudflare account has Pages enabled
|
|
128
|
+
|
|
129
|
+
## Local Development
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
npm run dev
|
|
133
|
+
# Visit: http://localhost:4321
|
|
134
|
+
# Test OG: http://localhost:4321/api/og/sdk
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Documentation
|
|
138
|
+
|
|
139
|
+
- [loopwind SDK Docs](/sdk)
|
|
140
|
+
- [OG Images Setup](./OG_IMAGES.md)
|
|
141
|
+
- [Cloudflare Astro Guide](https://developers.cloudflare.com/workers/framework-guides/web-apps/astro/)
|
|
142
|
+
|