stream_weaver 0.3.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.
- checksums.yaml +7 -0
- data/.beads/.gitignore +77 -0
- data/.beads/README.md +81 -0
- data/.beads/config.yaml +54 -0
- data/.beads/metadata.json +7 -0
- data/.rspec +3 -0
- data/AGENTS.md +91 -0
- data/CHANGELOG.md +294 -0
- data/CLAUDE.md +67 -0
- data/LICENSE.txt +21 -0
- data/README.md +565 -0
- data/Rakefile +13 -0
- data/assets/streamweaver-hero.jpg +0 -0
- data/bench/baselines/ledger.rb +58 -0
- data/bench/baselines/warroom.rb +51 -0
- data/bench/fixtures/ledger.rb +76 -0
- data/bench/fixtures/warroom.rb +60 -0
- data/bench/results/6daf8b8.md +102 -0
- data/bench/results/c8d749b.md +102 -0
- data/bench/results/eb06ab9.md +102 -0
- data/bench/run.rb +151 -0
- data/bench/support.rb +84 -0
- data/copy_this/dto_run_sample_run_7631.html +220 -0
- data/docs/SERVICE_MODE.md +302 -0
- data/docs/architecture/how_streamweaver_works.md +772 -0
- data/docs/blog/2026-01-16-streamweaver-introduction.md +515 -0
- data/docs/bug-2026-08-31-canvas-bridge-socket-collision.md +83 -0
- data/docs/canvas-ipc-session-summary.md +127 -0
- data/docs/canvas-panel-workflow.md +172 -0
- data/docs/canvas-read.md +147 -0
- data/docs/canvas-roadmap.md +275 -0
- data/docs/case-studies/2026-09-03-didx-canvas-read-shelf.md +147 -0
- data/docs/claude-code-companion-skill-spec.md +567 -0
- data/docs/components_reference.md +1223 -0
- data/docs/crud-patterns.md +265 -0
- data/docs/endpoints.md +122 -0
- data/docs/for_llms.md +1 -0
- data/docs/form-patterns.md +165 -0
- data/docs/frontend-only.md +169 -0
- data/docs/html-artifact-audit.md +238 -0
- data/docs/ideas/2025-01-01-as-a-service.md +203 -0
- data/docs/ideas/2026-01-16-charm-tui-exploration.md +542 -0
- data/docs/ideas/2026-08-27-static-doc-shelf-export.md +153 -0
- data/docs/ideas/dhh-review-future-refactors.md +142 -0
- data/docs/opal-jamstack.md +47 -0
- data/docs/opal-npm-direction.md +184 -0
- data/docs/opal-spike-findings.md +194 -0
- data/docs/plans/2025-12-16-form-blocks-design.md +124 -0
- data/docs/plans/2025-12-30-examples-browser-design.md +152 -0
- data/docs/plans/2026-01-02-charts-design.md +288 -0
- data/docs/plans/2026-01-10-canvas-ipc-design.md +247 -0
- data/docs/plans/2026-01-19-cabinet-control-components.md +176 -0
- data/docs/plans/2026-01-26-gem-release-and-panel.md +140 -0
- data/docs/plans/canvas-claude-project-design.md +238 -0
- data/docs/plans/canvas-doc-location-and-discovery.md +32 -0
- data/docs/plans/org-doc-preview-surfaces.md +293 -0
- data/docs/plans/shadcn-polish-plan.md +417 -0
- data/docs/porting-artifacts.md +252 -0
- data/docs/reference/agent-skills-comparison.md +369 -0
- data/docs/reference/travel-state-prd.artifact.html +780 -0
- data/docs/research/2026-08-17-hotwire-alike-landscape.md +268 -0
- data/docs/research/2026-08-17-hotwire-concept-map.md +404 -0
- data/docs/research/2026-08-22-lazy-fragments-trigger-decision.md +246 -0
- data/docs/research/2026-08-22-learnhotwire-syllabus-coverage.md +239 -0
- data/docs/research/frontend-only-matrix.md +278 -0
- data/docs/research/streamweaver-way-spike-findings.md +529 -0
- data/docs/resource-dsl.md +342 -0
- data/docs/routing.md +302 -0
- data/docs/ruby-ui-comparison.md +319 -0
- data/docs/shared-dsl-fragments.md +356 -0
- data/docs/streamweaver-for-ai-agents.md +401 -0
- data/docs/streamweaver-frontend-vision.md +123 -0
- data/docs/streamweaver_canvas/glimmer_initial_final_layer.rb +77 -0
- data/docs/streamweaver_canvas/save_example.rb +9 -0
- data/docs/templates.md +213 -0
- data/docs/testing.md +155 -0
- data/docs/theming-hooks.md +281 -0
- data/docs/tutorials/the-streamweaver-way.md +882 -0
- data/docs/university/capability-inventory.md +137 -0
- data/docs/university/dependency-survey.md +114 -0
- data/docs/university/design-spec.md +217 -0
- data/docs/university/mockups/code-block-doc-theme-dark.png +0 -0
- data/docs/university/mockups/code-block-doc-theme-light.png +0 -0
- data/docs/university/mockups/course-list-dark.png +0 -0
- data/docs/university/mockups/course-list-light.png +0 -0
- data/docs/university/mockups/course_canvas_mockup.rb +741 -0
- data/docs/university/mockups/step-screen-dark.png +0 -0
- data/docs/university/mockups/step-screen-light.png +0 -0
- data/docs/university/roadmap.md +72 -0
- data/docs/university/send-to-coworker.md +77 -0
- data/docs/university/worker-session-mining.md +109 -0
- data/docs/visual/browser-rendering-spike.md +173 -0
- data/docs/visual/builder-visual-plan-analysis.md +378 -0
- data/docs/visual/sw-plan-format-exploration.md +511 -0
- data/docs/visual/sw-plan-rendering-deep-dive.md +453 -0
- data/docs/visual-skills/PROGRESS.md +60 -0
- data/docs/visual-skills/SESSION-CONTEXT.md +207 -0
- data/docs/visual-skills/analysis/components.md +317 -0
- data/docs/visual-skills/analysis/overlap.md +360 -0
- data/docs/visual-skills/analysis/pi-design-deck.md +1102 -0
- data/docs/visual-skills/analysis/streamweaver-inventory.md +93 -0
- data/docs/visual-skills/analysis/unified-specs.feature +1003 -0
- data/docs/visual-skills/analysis/visual-explainer.md +964 -0
- data/docs/visual-skills/blog/blog-series-outline.md +39 -0
- data/docs/visual-skills/blog/token-efficiency.md +73 -0
- data/docs/visual-skills/design/architecture.md +1725 -0
- data/docs/visual-skills/design/codex-review.md +340 -0
- data/docs/visual-skills/design/dhh-review.md +209 -0
- data/docs/visual-skills/design/evolution.md +100 -0
- data/docs/visual-skills/design/gemini-review.md +55 -0
- data/docs/visual-skills/design/review-synthesis.md +149 -0
- data/docs/visual-skills/implementation/STATE.md +22 -0
- data/docs/visual-skills/implementation/plan.md +347 -0
- data/docs/visual-skills/implementation/spike-findings.md +237 -0
- data/docs/visual-skills/implementation/tasks.md +702 -0
- data/docs/visual-skills/lessons-learned/process.md +145 -0
- data/examples/README.md +96 -0
- data/examples/advanced/all_components.rb +177 -0
- data/examples/advanced/examples_browser.rb +394 -0
- data/examples/advanced/teachables_browser.rb +261 -0
- data/examples/advanced/theme_tweaker.rb +366 -0
- data/examples/advanced/tutorial.rb +1528 -0
- data/examples/agentic/agentic_form.rb +30 -0
- data/examples/agentic/agentic_form_autoclose.rb +30 -0
- data/examples/agentic/cultivation_tracker.rb +69 -0
- data/examples/basic/hello_world.rb +22 -0
- data/examples/basic/opal_tabs_table.rb +44 -0
- data/examples/basic/todo_list.rb +39 -0
- data/examples/button_loading_test.rb +36 -0
- data/examples/canvas/mermaid_canvas_demo.sh +151 -0
- data/examples/charts/bar_chart_demo.rb +57 -0
- data/examples/charts/line_chart_demo.rb +73 -0
- data/examples/charts/pie_area_demo.rb +87 -0
- data/examples/charts/stacked_bar_chart_demo.rb +69 -0
- data/examples/claude_code/README.md +85 -0
- data/examples/claude_code/codebreaker/.claude/commands/infiltrate.md +632 -0
- data/examples/claude_code/codebreaker/.claude/settings.json +11 -0
- data/examples/claude_code/codebreaker/.claude/settings.local.json +17 -0
- data/examples/claude_code/codebreaker/.claude/skills/infiltrate.md +0 -0
- data/examples/claude_code/codebreaker/README.md +213 -0
- data/examples/claude_code/tutorial/.claude/commands/learn.md +453 -0
- data/examples/claude_code/tutorial/README.md +102 -0
- data/examples/claude_code/verification_flow/.claude/commands/verify.md +171 -0
- data/examples/claude_code/verification_flow/README.md +126 -0
- data/examples/components/annotated_code_demo.rb +54 -0
- data/examples/components/callout_demo.rb +33 -0
- data/examples/components/checkbox_group_demo.rb +46 -0
- data/examples/components/design_review.css +468 -0
- data/examples/components/design_review_demo.rb +44 -0
- data/examples/components/design_review_dsl.rb +300 -0
- data/examples/components/diff_block_demo.rb +112 -0
- data/examples/components/events_demo.rb +184 -0
- data/examples/components/form_demo.rb +62 -0
- data/examples/components/lesson_demo.rb +53 -0
- data/examples/components/markdown_demo.rb +110 -0
- data/examples/components/mermaid_demo.rb +166 -0
- data/examples/components/pareto_set.rb +64 -0
- data/examples/components/prd_demo.rb +21 -0
- data/examples/components/prd_dsl.rb +385 -0
- data/examples/components/quiz_demo.rb +47 -0
- data/examples/components/run_viewer_demo.rb +100 -0
- data/examples/components/score_and_collapsible_demo.rb +82 -0
- data/examples/components/select_stale_value_smoke_test.rb +39 -0
- data/examples/components/table_demo.rb +247 -0
- data/examples/components/timer_with_state_demo.rb +58 -0
- data/examples/components/todo_due_dates.rb +63 -0
- data/examples/components/uat_gaps_demo.rb +112 -0
- data/examples/dashboard/feed_simulator.rb +60 -0
- data/examples/dashboard/live_dashboard.rb +80 -0
- data/examples/dashboard_components.rb +108 -0
- data/examples/deferred_fragments_demo.rb +62 -0
- data/examples/generate_more_spike/README.md +63 -0
- data/examples/generate_more_spike/app.rb +441 -0
- data/examples/git_health.sh +401 -0
- data/examples/layout/layout_components_demo.rb +174 -0
- data/examples/layout/modal_demo.rb +215 -0
- data/examples/layout/navigation_demo.rb +227 -0
- data/examples/layout/route_tabs_demo.rb +52 -0
- data/examples/layout/routing_demo.rb +52 -0
- data/examples/layout/scroll_box_demo.rb +154 -0
- data/examples/lazy_fragments_demo.rb +151 -0
- data/examples/my_todos/README.md +29 -0
- data/examples/my_todos/my_todos.rb +312 -0
- data/examples/my_todos/store.rb +86 -0
- data/examples/opal/reactive_demo.rb +62 -0
- data/examples/opal/scenarios/s1_counter.rb +15 -0
- data/examples/opal/scenarios/s2_search_filter.rb +17 -0
- data/examples/opal/scenarios/s3_sibling_tabs.rb +25 -0
- data/examples/opal/scenarios/s4_shopping_cart.rb +34 -0
- data/examples/opal/scenarios/s5_watch.rb +39 -0
- data/examples/opal/scenarios/s6_on_start.rb +20 -0
- data/examples/opal/scenarios/s7_wizard.rb +33 -0
- data/examples/opal/scenarios/s8_loan_calculator.rb +21 -0
- data/examples/opal/scenarios/s9_dashboard.rb +27 -0
- data/examples/operations_dashboard_demo.rb +167 -0
- data/examples/panel_demo.sh +447 -0
- data/examples/parity/assets/tyrion_slice.css +86 -0
- data/examples/parity/rivet_people_slice.rb +182 -0
- data/examples/parity/tyrion_components.css +777 -0
- data/examples/parity/tyrion_warroom_components.rb +414 -0
- data/examples/parity/tyrion_warroom_slice.rb +549 -0
- data/examples/puma_dev/README.md +124 -0
- data/examples/puma_dev/config.ru +34 -0
- data/examples/puma_dev/standalone_app.rb +34 -0
- data/examples/scaffolding/blog.rb +49 -0
- data/examples/scaffolding/utf_lite.rb +105 -0
- data/examples/styling/feedback_demo.rb +229 -0
- data/examples/styling/style_showcase.rb +172 -0
- data/examples/styling/theme_demo.rb +508 -0
- data/examples/timer_health_checker.rb +111 -0
- data/examples/timer_showcase.rb +131 -0
- data/examples/tutorials/render_markdown.rb +112 -0
- data/examples/tutorials/streamweaver_way_tutorial.rb +44 -0
- data/examples/tutorials/tutorial_content.rb +1082 -0
- data/examples/visual_skills/design_deck_demo.rb +314 -0
- data/examples/visual_skills/explainer_demo.rb +499 -0
- data/exe/streamweaver +9 -0
- data/gsd/ROADMAP-1.0.md +167 -0
- data/gsd/STATE.md +13 -0
- data/gsd/research/market-positioning-research.md +139 -0
- data/gsd/research/production-patterns-research.md +270 -0
- data/gsd/research/repo-audit-1.0.md +274 -0
- data/lib/stream_weaver/action_token.rb +58 -0
- data/lib/stream_weaver/adapter/alpinejs.rb +8249 -0
- data/lib/stream_weaver/adapter/base.rb +591 -0
- data/lib/stream_weaver/adapter/opal.rb +334 -0
- data/lib/stream_weaver/adapter/static.rb +1118 -0
- data/lib/stream_weaver/admin.rb +176 -0
- data/lib/stream_weaver/app.rb +1821 -0
- data/lib/stream_weaver/assets/js/sw-copy.js +50 -0
- data/lib/stream_weaver/assets/js/sw-heredoc-rewrite.js +68 -0
- data/lib/stream_weaver/assets/js/sw-keyboard.js +165 -0
- data/lib/stream_weaver/assets/js/sw-mermaid-zoom.js +621 -0
- data/lib/stream_weaver/assets/js/sw-route-tabs.js +53 -0
- data/lib/stream_weaver/assets/js/sw-sidebar-toc.js +116 -0
- data/lib/stream_weaver/assets/js/sw-slide-nav.js +103 -0
- data/lib/stream_weaver/canvas/bridge.rb +239 -0
- data/lib/stream_weaver/canvas/bridge_server.rb +646 -0
- data/lib/stream_weaver/canvas/client.rb +298 -0
- data/lib/stream_weaver/canvas/doc_roots.rb +233 -0
- data/lib/stream_weaver/canvas/doc_store.rb +252 -0
- data/lib/stream_weaver/canvas/gist_publisher.rb +264 -0
- data/lib/stream_weaver/canvas/gist_save_handler.rb +89 -0
- data/lib/stream_weaver/canvas/gist_store.rb +135 -0
- data/lib/stream_weaver/canvas/helpers.rb +109 -0
- data/lib/stream_weaver/canvas/history.rb +90 -0
- data/lib/stream_weaver/canvas/protocol.rb +86 -0
- data/lib/stream_weaver/canvas/reader.rb +853 -0
- data/lib/stream_weaver/canvas/save_doc_widget.rb +457 -0
- data/lib/stream_weaver/canvas/scroll_top_hint.rb +21 -0
- data/lib/stream_weaver/canvas/session.rb +132 -0
- data/lib/stream_weaver/cli.rb +3235 -0
- data/lib/stream_weaver/component_assets.rb +70 -0
- data/lib/stream_weaver/component_registry.rb +67 -0
- data/lib/stream_weaver/component_renderer.rb +48 -0
- data/lib/stream_weaver/components/annotated_code.rb +53 -0
- data/lib/stream_weaver/components/api_endpoint.rb +42 -0
- data/lib/stream_weaver/components/callout.rb +59 -0
- data/lib/stream_weaver/components/chart.rb +84 -0
- data/lib/stream_weaver/components/code_block.rb +77 -0
- data/lib/stream_weaver/components/comparison.rb +39 -0
- data/lib/stream_weaver/components/decision.rb +38 -0
- data/lib/stream_weaver/components/deck/close_overlay.rb +84 -0
- data/lib/stream_weaver/components/deck/confirmation_bar.rb +60 -0
- data/lib/stream_weaver/components/deck/deck_option.rb +61 -0
- data/lib/stream_weaver/components/deck/deck_slide.rb +77 -0
- data/lib/stream_weaver/components/deck/deck_state.rb +469 -0
- data/lib/stream_weaver/components/deck/deck_summary.rb +73 -0
- data/lib/stream_weaver/components/deck/design_deck.rb +60 -0
- data/lib/stream_weaver/components/deck/generate_more_controls.rb +84 -0
- data/lib/stream_weaver/components/deck/model_selector.rb +84 -0
- data/lib/stream_weaver/components/deck/skeleton_placeholder.rb +36 -0
- data/lib/stream_weaver/components/diff_block.rb +125 -0
- data/lib/stream_weaver/components/doc_header.rb +57 -0
- data/lib/stream_weaver/components/image_block.rb +70 -0
- data/lib/stream_weaver/components/implementation_map.rb +33 -0
- data/lib/stream_weaver/components/keyboard_shortcuts.rb +94 -0
- data/lib/stream_weaver/components/kpi_dashboard.rb +78 -0
- data/lib/stream_weaver/components/mermaid.rb +79 -0
- data/lib/stream_weaver/components/pipeline.rb +63 -0
- data/lib/stream_weaver/components/sidebar_toc.rb +46 -0
- data/lib/stream_weaver/components/slide_container.rb +141 -0
- data/lib/stream_weaver/components/timeline_event.rb +58 -0
- data/lib/stream_weaver/components/wireframe.rb +29 -0
- data/lib/stream_weaver/components/wireframe_block.rb +34 -0
- data/lib/stream_weaver/components.rb +2711 -0
- data/lib/stream_weaver/css.rb +230 -0
- data/lib/stream_weaver/dev_fallback_overlay.rb +61 -0
- data/lib/stream_weaver/display_dsl.rb +1004 -0
- data/lib/stream_weaver/export/html_exporter.rb +478 -0
- data/lib/stream_weaver/feed.rb +34 -0
- data/lib/stream_weaver/feed_builder.rb +31 -0
- data/lib/stream_weaver/fonts.rb +33 -0
- data/lib/stream_weaver/interaction_runner.rb +487 -0
- data/lib/stream_weaver/iterm.rb +460 -0
- data/lib/stream_weaver/layout_registry.rb +92 -0
- data/lib/stream_weaver/opal/bridge.rb +52 -0
- data/lib/stream_weaver/opal/builder.rb +193 -0
- data/lib/stream_weaver/opal/env.rb +29 -0
- data/lib/stream_weaver/opal/reactive_state.rb +75 -0
- data/lib/stream_weaver/opal/regexp_anchor_patch.rb +62 -0
- data/lib/stream_weaver/opal/renderer.rb +77 -0
- data/lib/stream_weaver/opal/runtime.rb +250 -0
- data/lib/stream_weaver/opal/shell.rb +145 -0
- data/lib/stream_weaver/opal/string_bridge.rb +50 -0
- data/lib/stream_weaver/opal/stubs/diff.min.js +1 -0
- data/lib/stream_weaver/opal/stubs/digest.rb +15 -0
- data/lib/stream_weaver/opal/stubs/marked.umd.js +79 -0
- data/lib/stream_weaver/opal/stubs/md5.rb +3 -0
- data/lib/stream_weaver/opal/stubs/morphdom.min.js +775 -0
- data/lib/stream_weaver/opal/stubs/prism-tomorrow.min.css +1 -0
- data/lib/stream_weaver/opal/stubs/prism.min.js +1967 -0
- data/lib/stream_weaver/opal_entry.rb +136 -0
- data/lib/stream_weaver/org/inline.rb +95 -0
- data/lib/stream_weaver/org/reader.rb +561 -0
- data/lib/stream_weaver/org/recording_context.rb +86 -0
- data/lib/stream_weaver/org/source_splitter.rb +63 -0
- data/lib/stream_weaver/org/writer.rb +300 -0
- data/lib/stream_weaver/page_shell.rb +530 -0
- data/lib/stream_weaver/portfile.rb +79 -0
- data/lib/stream_weaver/pushable.rb +42 -0
- data/lib/stream_weaver/resource/default_views.rb +111 -0
- data/lib/stream_weaver/resource/field_input.rb +25 -0
- data/lib/stream_weaver/resource/state_keys.rb +16 -0
- data/lib/stream_weaver/resource/store.rb +18 -0
- data/lib/stream_weaver/resource.rb +104 -0
- data/lib/stream_weaver/server.rb +1471 -0
- data/lib/stream_weaver/service.rb +1240 -0
- data/lib/stream_weaver/service_client.rb +104 -0
- data/lib/stream_weaver/session_store.rb +186 -0
- data/lib/stream_weaver/skills/streamweaver-canvas-safe/SKILL.md +66 -0
- data/lib/stream_weaver/skills/streamweaver-canvas-safe/examples/canvas-safe-showcase.rb +98 -0
- data/lib/stream_weaver/skills/streamweaver-canvas-safe/references/actions-and-buttons.md +47 -0
- data/lib/stream_weaver/skills/streamweaver-canvas-safe/references/charts-and-diagrams.md +38 -0
- data/lib/stream_weaver/skills/streamweaver-canvas-safe/references/deck.md +32 -0
- data/lib/stream_weaver/skills/streamweaver-canvas-safe/references/inputs-and-forms.md +65 -0
- data/lib/stream_weaver/skills/streamweaver-canvas-safe/references/tabs-and-navigation.md +53 -0
- data/lib/stream_weaver/skills/streamweaver-doc-builder/SKILL.md +298 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/SKILL.md +130 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/examples/design-review-example.css +468 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/examples/design-review-example.rb +39 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/examples/design-review-example_dsl.rb +300 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/examples/doc-parity-example.rb +24 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/examples/doc-parity-example_dsl.rb +385 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/references/checkpoints-and-forms.md +28 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/references/cleanup-and-panel.md +44 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/references/example-gallery.md +8 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/references/persistence.md +58 -0
- data/lib/stream_weaver/skills/streamweaver-way/SKILL.md +396 -0
- data/lib/stream_weaver/skills/visual-plan/SKILL.md +201 -0
- data/lib/stream_weaver/skills/visual-recap/SKILL.md +244 -0
- data/lib/stream_weaver/streamer.rb +63 -0
- data/lib/stream_weaver/templates/choices.rb +149 -0
- data/lib/stream_weaver/templates/code.rb +157 -0
- data/lib/stream_weaver/templates/confirm.rb +110 -0
- data/lib/stream_weaver/templates/diff.rb +195 -0
- data/lib/stream_weaver/templates/info.rb +142 -0
- data/lib/stream_weaver/templates/table.rb +169 -0
- data/lib/stream_weaver/templates/wizard.rb +271 -0
- data/lib/stream_weaver/theme/auto_mode.rb +116 -0
- data/lib/stream_weaver/theme/presets.rb +555 -0
- data/lib/stream_weaver/theme.rb +639 -0
- data/lib/stream_weaver/university/canvas.rb +924 -0
- data/lib/stream_weaver/university/course.rb +699 -0
- data/lib/stream_weaver/university/demos/counter.rb +33 -0
- data/lib/stream_weaver/university/demos/dashboard.rb +147 -0
- data/lib/stream_weaver/university/demos/decision_form.rb +143 -0
- data/lib/stream_weaver/university/demos.rb +50 -0
- data/lib/stream_weaver/university/listener.rb +467 -0
- data/lib/stream_weaver/university/progress.rb +201 -0
- data/lib/stream_weaver/university/runner.rb +138 -0
- data/lib/stream_weaver/university/scripts/growing_doc.rb +609 -0
- data/lib/stream_weaver/university/scripts/growing_doc_state.rb +91 -0
- data/lib/stream_weaver/utils.rb +31 -0
- data/lib/stream_weaver/version.rb +5 -0
- data/lib/stream_weaver/views/canvas/reader_layout.erb +800 -0
- data/lib/stream_weaver/views.rb +3940 -0
- data/lib/stream_weaver.rb +122 -0
- data/llms.txt +1269 -0
- data/sig/stream_weaver.rbs +4 -0
- metadata +598 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# backtick_javascript: true
|
|
3
|
+
# Browser-only require tree. Does NOT require Sinatra, Phlex, AlpineJS,
|
|
4
|
+
# iTerm, service, service_client, admin, streamer, feed, or cli.
|
|
5
|
+
|
|
6
|
+
require "stream_weaver/version"
|
|
7
|
+
require "stream_weaver/utils"
|
|
8
|
+
require "stream_weaver/css" # layer_wrap, for per-component CSS injection
|
|
9
|
+
require "stream_weaver/theme"
|
|
10
|
+
require "stream_weaver/display_dsl"
|
|
11
|
+
require "stream_weaver/app"
|
|
12
|
+
require "stream_weaver/components"
|
|
13
|
+
require "stream_weaver/adapter/base"
|
|
14
|
+
# Phase 1 placeholders — implemented in subsequent tasks:
|
|
15
|
+
require "stream_weaver/adapter/opal"
|
|
16
|
+
require "stream_weaver/opal/renderer"
|
|
17
|
+
require "stream_weaver/opal/runtime"
|
|
18
|
+
require "stream_weaver/opal/bridge"
|
|
19
|
+
require "stream_weaver/opal/string_bridge"
|
|
20
|
+
|
|
21
|
+
# Opal-specific patches: fix methods that break in the browser.
|
|
22
|
+
|
|
23
|
+
# App#button and DisplayDSL#button use block.source_location.join(':').
|
|
24
|
+
# In Opal, source_location returns nil (no source maps in compiled JS).
|
|
25
|
+
# Override button in App to use a counter-based stable_id instead.
|
|
26
|
+
module StreamWeaver
|
|
27
|
+
module Opal
|
|
28
|
+
module AppButtonPatch
|
|
29
|
+
# Opal: source_location is nil — use counter-based IDs. Counter ids are
|
|
30
|
+
# already unique per render, so there is nothing to disambiguate here;
|
|
31
|
+
# id:/key: are still honored (same id: > key: > auto precedence) so a
|
|
32
|
+
# keyed button keeps its identity across rerenders, and so neither
|
|
33
|
+
# option leaks into the rendered element's attributes.
|
|
34
|
+
def button(label, key: nil, id: nil, **options, &block)
|
|
35
|
+
@button_counter += 1
|
|
36
|
+
identity = id || key
|
|
37
|
+
stable_id = identity ? "opal_#{identity}" : "opal_#{@button_counter}"
|
|
38
|
+
options[:modal_context] = @modal_context if @modal_context
|
|
39
|
+
@components << Components::Button.new(label, stable_id, **options, &block)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
StreamWeaver::App.prepend StreamWeaver::Opal::AppButtonPatch
|
|
45
|
+
|
|
46
|
+
module StreamWeaver
|
|
47
|
+
module Opal
|
|
48
|
+
module AppReactivePatch
|
|
49
|
+
def watch(key, &block)
|
|
50
|
+
rt = OpalRuntime.current
|
|
51
|
+
return unless rt && !rt.watchers_initialized?
|
|
52
|
+
rt.state.watch(key) do |val|
|
|
53
|
+
block.call(val)
|
|
54
|
+
rt.schedule_rerender
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def on_start(&block)
|
|
59
|
+
OpalRuntime.current&.register_start_hook(block)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def after(seconds, &block)
|
|
63
|
+
return unless RUBY_ENGINE == "opal"
|
|
64
|
+
ms = (seconds * 1000).to_i
|
|
65
|
+
cb = block
|
|
66
|
+
# :nocov:
|
|
67
|
+
%x{ setTimeout(function() { #{cb.call} }, #{ms}) }
|
|
68
|
+
# :nocov:
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def every(seconds, &block)
|
|
72
|
+
return unless RUBY_ENGINE == "opal"
|
|
73
|
+
ms = (seconds * 1000).to_i
|
|
74
|
+
cb = block
|
|
75
|
+
# :nocov:
|
|
76
|
+
%x{ setInterval(function() { #{cb.call} }, #{ms}) }
|
|
77
|
+
# :nocov:
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def defer(&block)
|
|
81
|
+
return unless RUBY_ENGINE == "opal"
|
|
82
|
+
cb = block
|
|
83
|
+
# :nocov:
|
|
84
|
+
%x{ setTimeout(function() { #{cb.call} }, 0) }
|
|
85
|
+
# :nocov:
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
StreamWeaver::App.prepend StreamWeaver::Opal::AppReactivePatch
|
|
91
|
+
|
|
92
|
+
# Opal-mode global `app` helper — replaces the Sinatra-wired StreamWeaver.app.
|
|
93
|
+
# Creates an OpalRuntime with the DSL block, publishes it to JavaScript, and
|
|
94
|
+
# returns the runtime.
|
|
95
|
+
#
|
|
96
|
+
# Two bridges, because the same compiled bundle runs in two hosts. OpalBridge
|
|
97
|
+
# (window.SWRuntime: patching, event delegation) needs a DOM and installs only
|
|
98
|
+
# when it finds one, so loading this bundle in Node no longer explodes on the
|
|
99
|
+
# missing `window`. StringBridge (globalThis.SWRender) needs nothing and always
|
|
100
|
+
# installs, which is what gives a Node process a way to render the doc to a
|
|
101
|
+
# string. `app()` keeps its original signature so existing browser builds and
|
|
102
|
+
# opal-build output are unaffected.
|
|
103
|
+
module StreamWeaver
|
|
104
|
+
# App#initialize (app.rb) calls StreamWeaver.strict_ids? unconditionally
|
|
105
|
+
# to seed @strict_ids when the caller doesn't pass strict_ids: explicitly.
|
|
106
|
+
# The real definition (lib/stream_weaver.rb) checks an ivar + the
|
|
107
|
+
# SW_STRICT_IDS env var, but that file also requires server/service/cli/
|
|
108
|
+
# admin/iterm -- none of them Opal-compatible, which is exactly why this
|
|
109
|
+
# file (opal_entry.rb) requires app.rb directly and never requires
|
|
110
|
+
# lib/stream_weaver.rb itself. That left StreamWeaver.strict_ids?
|
|
111
|
+
# undefined in every Opal build (this extension, opal-build's standalone
|
|
112
|
+
# HTML output) the moment app.rb started calling it -- "undefined method
|
|
113
|
+
# `strict_ids?' for StreamWeaver", reproduced live against a rebuilt
|
|
114
|
+
# extension bundle. Always false here, not a stub of the real check: both
|
|
115
|
+
# Opal hosts only ever render a doc once, non-interactively (SWRuntime.
|
|
116
|
+
# start() is never called for the extension's static preview; opal-build's
|
|
117
|
+
# standalone HTML is likewise a one-shot render), so there is no
|
|
118
|
+
# interactive id-collision risk for strict mode to catch in either one.
|
|
119
|
+
def self.strict_ids?
|
|
120
|
+
false
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
module Opal
|
|
124
|
+
module Kernel
|
|
125
|
+
def app(title, **_opts, &block)
|
|
126
|
+
adapter = Adapter::Opal.new
|
|
127
|
+
runtime = OpalRuntime.new(adapter: adapter)
|
|
128
|
+
runtime.set_block(&block)
|
|
129
|
+
OpalBridge.new(runtime).install
|
|
130
|
+
StringBridge.new(runtime, title: title).install
|
|
131
|
+
runtime
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
include StreamWeaver::Opal::Kernel
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module StreamWeaver
|
|
4
|
+
module Org
|
|
5
|
+
# Bidirectional inline markup conversion between markdown (as used inside
|
|
6
|
+
# `md "..."` DSL calls) and org-mode inline syntax. Boundary-aware: a
|
|
7
|
+
# delimiter only opens/closes a span when flanked the way org itself
|
|
8
|
+
# requires, so literal characters in file paths ("app/admin/cms/foo.rb")
|
|
9
|
+
# or "X / Y" phrasing are never misread as emphasis markers.
|
|
10
|
+
module Inline
|
|
11
|
+
PRE = /(?:\A|[\s\("])/.source
|
|
12
|
+
POST = /(?:\z|[\s\.,;:!?\)"])/.source
|
|
13
|
+
|
|
14
|
+
# Lookaround (not capturing) so the boundary character is never
|
|
15
|
+
# "consumed" -- otherwise two adjacent spans sharing one space between
|
|
16
|
+
# them ("*a* *b*") corrupt into one mismatched span, since the shared
|
|
17
|
+
# space gets eaten as POST of the first match and is then unavailable
|
|
18
|
+
# as PRE for the second. Content also excludes the delimiter itself
|
|
19
|
+
# (not just the first/last char) -- this is what stops ITALIC_MD's
|
|
20
|
+
# single-"*" pattern from misreading BOLD_MD's doubled "**" markers as
|
|
21
|
+
# its own boundary (the second "*" of "**bold**" can never be content).
|
|
22
|
+
def self.span(delim)
|
|
23
|
+
d = Regexp.escape(delim)
|
|
24
|
+
/(?<=#{PRE})#{d}([^\s#{d}](?:[^#{d}]*?[^\s#{d}])?)#{d}(?=#{POST})/m
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Code/verbatim spans have no doubled-marker sibling to disambiguate
|
|
28
|
+
# against (unlike "*"/"**"), so unlike span() this allows the delimiter
|
|
29
|
+
# itself inside the content -- real code routinely contains "="
|
|
30
|
+
# (e.g. "queued=true"). The trailing group must be a LAZY optional
|
|
31
|
+
# (`??`, not `?`) -- a greedy optional always tries "include extra
|
|
32
|
+
# content" first, and backtracking from there finds the *last* valid
|
|
33
|
+
# closing delimiter on the line, bridging separate spans ("`a` `b`"
|
|
34
|
+
# -> content "a` `b"). Lazy-optional tries "no extra content" first,
|
|
35
|
+
# so it finds the *nearest* closing delimiter whose following
|
|
36
|
+
# character satisfies POST -- correct for both a single span whose
|
|
37
|
+
# content happens to contain the delimiter, and two adjacent spans.
|
|
38
|
+
def self.code_span(delim)
|
|
39
|
+
d = Regexp.escape(delim)
|
|
40
|
+
/(?<=#{PRE})#{d}([^\s](?:.*?[^\s])??)#{d}(?=#{POST})/m
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
BOLD_MD = span("**")
|
|
44
|
+
ITALIC_MD = span("*")
|
|
45
|
+
CODE_MD = code_span("`")
|
|
46
|
+
# Org's own [[target][text]] link is generic across target shapes --
|
|
47
|
+
# an internal #anchor, a relative path, an external URL, all render
|
|
48
|
+
# identically as a plain <a href> in a real org viewer (verified
|
|
49
|
+
# against org-ruby, the gem GitHub/markymark also use: stream_weaver-043f).
|
|
50
|
+
# No "#" requirement, so neither should this converter's match.
|
|
51
|
+
LINK_MD = /\[([^\]]+)\]\(([^\)]+)\)/
|
|
52
|
+
|
|
53
|
+
BOLD_ORG = span("*")
|
|
54
|
+
ITALIC_ORG = span("/")
|
|
55
|
+
CODE_ORG = code_span("=")
|
|
56
|
+
LINK_ORG = /\[\[([^\]]+)\]\[([^\]]+)\]\]/
|
|
57
|
+
|
|
58
|
+
PLACEHOLDER = "\x00CODE%d\x00"
|
|
59
|
+
PLACEHOLDER_RE = /\x00CODE(\d+)\x00/
|
|
60
|
+
|
|
61
|
+
def self.md_to_org(text)
|
|
62
|
+
text, protected_spans = extract(text, CODE_MD)
|
|
63
|
+
text = text.gsub(LINK_MD) { "[[#{$2}][#{$1}]]" }
|
|
64
|
+
text = text.gsub(ITALIC_MD) { "/#{$1}/" }
|
|
65
|
+
text = text.gsub(BOLD_MD) { "*#{$1}*" }
|
|
66
|
+
text = text.gsub(/~(?=\d)/, "≈")
|
|
67
|
+
restore(text, protected_spans) { |content| "=#{content}=" }
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def self.org_to_md(text)
|
|
71
|
+
text, protected_spans = extract(text, CODE_ORG)
|
|
72
|
+
text = text.gsub(LINK_ORG) { "[#{$2}](#{$1})" }
|
|
73
|
+
text = text.gsub(BOLD_ORG) { "**#{$1}**" }
|
|
74
|
+
text = text.gsub(ITALIC_ORG) { "*#{$1}*" }
|
|
75
|
+
restore(text, protected_spans) { |content| "`#{content}`" }
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Replaces every code/verbatim span with a placeholder token so later
|
|
79
|
+
# passes (link/bold/italic/tilde) never see -- and can't corrupt --
|
|
80
|
+
# content that's supposed to stay literal.
|
|
81
|
+
def self.extract(text, code_pattern)
|
|
82
|
+
spans = []
|
|
83
|
+
replaced = text.gsub(code_pattern) do
|
|
84
|
+
spans << $1
|
|
85
|
+
PLACEHOLDER % (spans.length - 1)
|
|
86
|
+
end
|
|
87
|
+
[replaced, spans]
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def self.restore(text, spans)
|
|
91
|
+
text.gsub(PLACEHOLDER_RE) { yield spans[$1.to_i] }
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|