quantum-framework 0.18.0__py3-none-any.whl
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.
- quantum/__init__.py +1 -0
- quantum/cli/__init__.py +2 -0
- quantum/cli/admin.py +131 -0
- quantum/cli/check.py +223 -0
- quantum/cli/commands/__init__.py +15 -0
- quantum/cli/commands/build.py +414 -0
- quantum/cli/commands/dev.py +185 -0
- quantum/cli/commands/docs.py +329 -0
- quantum/cli/commands/lint.py +523 -0
- quantum/cli/commands/migrate.py +548 -0
- quantum/cli/commands/new.py +622 -0
- quantum/cli/commands/serve.py +190 -0
- quantum/cli/commands/test.py +193 -0
- quantum/cli/deploy.py +810 -0
- quantum/cli/hot_reload.py +951 -0
- quantum/cli/jobs.py +356 -0
- quantum/cli/mq.py +582 -0
- quantum/cli/pkg.py +390 -0
- quantum/cli/runner.py +565 -0
- quantum/cli/server_process.py +159 -0
- quantum/cli/utils.py +334 -0
- quantum/compiler/__init__.py +30 -0
- quantum/compiler/base_generator.py +367 -0
- quantum/compiler/cli.py +295 -0
- quantum/compiler/expression_transformer.py +444 -0
- quantum/compiler/javascript/__init__.py +10 -0
- quantum/compiler/javascript/generator.py +659 -0
- quantum/compiler/optimizer.py +270 -0
- quantum/compiler/python/__init__.py +10 -0
- quantum/compiler/python/generator.py +883 -0
- quantum/compiler/python/runtime.py +863 -0
- quantum/compiler/transpiler.py +330 -0
- quantum/core/__init__.py +3 -0
- quantum/core/ast_nodes.py +2619 -0
- quantum/core/config_env.py +54 -0
- quantum/core/docs_links.py +8 -0
- quantum/core/expression_diagnostics.py +87 -0
- quantum/core/expression_stdlib.py +208 -0
- quantum/core/expressions.py +677 -0
- quantum/core/features/agents/src/__init__.py +30 -0
- quantum/core/features/agents/src/ast_node.py +540 -0
- quantum/core/features/conditionals/src/__init__.py +8 -0
- quantum/core/features/conditionals/src/ast_node.py +68 -0
- quantum/core/features/data_import/src/__init__.py +0 -0
- quantum/core/features/data_import/src/ast_node.py +292 -0
- quantum/core/features/data_import/src/runtime.py +533 -0
- quantum/core/features/dump/src/__init__.py +12 -0
- quantum/core/features/dump/src/ast_node.py +106 -0
- quantum/core/features/dump/src/parser.py +61 -0
- quantum/core/features/dump/src/runtime.py +246 -0
- quantum/core/features/functions/src/__init__.py +8 -0
- quantum/core/features/functions/src/ast_node.py +149 -0
- quantum/core/features/game_engine_2d/src/__init__.py +19 -0
- quantum/core/features/game_engine_2d/src/ast_nodes.py +1719 -0
- quantum/core/features/game_engine_2d/src/parser.py +983 -0
- quantum/core/features/invocation/src/__init__.py +0 -0
- quantum/core/features/invocation/src/ast_node.py +147 -0
- quantum/core/features/invocation/src/runtime.py +332 -0
- quantum/core/features/knowledge_base/src/__init__.py +6 -0
- quantum/core/features/knowledge_base/src/ast_node.py +113 -0
- quantum/core/features/knowledge_base/src/parser.py +82 -0
- quantum/core/features/logging/src/__init__.py +12 -0
- quantum/core/features/logging/src/ast_node.py +111 -0
- quantum/core/features/logging/src/parser.py +50 -0
- quantum/core/features/logging/src/runtime.py +190 -0
- quantum/core/features/loops/src/__init__.py +8 -0
- quantum/core/features/loops/src/ast_node.py +60 -0
- quantum/core/features/query/src/__init__.py +0 -0
- quantum/core/features/query/src/query_validators.py +20 -0
- quantum/core/features/state_management/src/__init__.py +11 -0
- quantum/core/features/state_management/src/ast_node.py +121 -0
- quantum/core/features/terminal_engine/src/__init__.py +21 -0
- quantum/core/features/terminal_engine/src/ast_nodes.py +560 -0
- quantum/core/features/terminal_engine/src/parser.py +361 -0
- quantum/core/features/testing_engine/src/__init__.py +41 -0
- quantum/core/features/testing_engine/src/ast_nodes.py +1212 -0
- quantum/core/features/testing_engine/src/parser.py +604 -0
- quantum/core/features/theming/src/__init__.py +48 -0
- quantum/core/features/theming/src/ast_node.py +137 -0
- quantum/core/features/theming/src/presets.py +405 -0
- quantum/core/features/ui_engine/src/__init__.py +20 -0
- quantum/core/features/ui_engine/src/ast_nodes.py +1913 -0
- quantum/core/features/ui_engine/src/parser.py +1192 -0
- quantum/core/features/websocket/src/__init__.py +24 -0
- quantum/core/features/websocket/src/ast_node.py +247 -0
- quantum/core/guards.py +53 -0
- quantum/core/html_compat.py +299 -0
- quantum/core/parser.py +1551 -0
- quantum/core/parser_registry.py +213 -0
- quantum/core/parsers/__init__.py +76 -0
- quantum/core/parsers/ai/__init__.py +12 -0
- quantum/core/parsers/ai/agent_parser.py +106 -0
- quantum/core/parsers/ai/knowledge_parser.py +86 -0
- quantum/core/parsers/ai/llm_parser.py +78 -0
- quantum/core/parsers/ai/team_parser.py +88 -0
- quantum/core/parsers/base.py +322 -0
- quantum/core/parsers/composition/__init__.py +10 -0
- quantum/core/parsers/composition/import_parser.py +50 -0
- quantum/core/parsers/composition/slot_parser.py +48 -0
- quantum/core/parsers/control_flow/__init__.py +11 -0
- quantum/core/parsers/control_flow/if_parser.py +71 -0
- quantum/core/parsers/control_flow/loop_parser.py +105 -0
- quantum/core/parsers/control_flow/set_parser.py +93 -0
- quantum/core/parsers/data/__init__.py +12 -0
- quantum/core/parsers/data/data_parser.py +229 -0
- quantum/core/parsers/data/invoke_parser.py +133 -0
- quantum/core/parsers/data/query_parser.py +213 -0
- quantum/core/parsers/data/transaction_parser.py +86 -0
- quantum/core/parsers/events/__init__.py +9 -0
- quantum/core/parsers/events/dispatch_event_parser.py +44 -0
- quantum/core/parsers/forms/__init__.py +11 -0
- quantum/core/parsers/forms/action_parser.py +79 -0
- quantum/core/parsers/forms/flash_parser.py +34 -0
- quantum/core/parsers/forms/redirect_parser.py +33 -0
- quantum/core/parsers/functions/__init__.py +11 -0
- quantum/core/parsers/functions/function_parser.py +98 -0
- quantum/core/parsers/functions/param_parser.py +73 -0
- quantum/core/parsers/functions/return_parser.py +31 -0
- quantum/core/parsers/html/__init__.py +10 -0
- quantum/core/parsers/html/component_call_parser.py +130 -0
- quantum/core/parsers/html/html_parser.py +115 -0
- quantum/core/parsers/jobs/__init__.py +11 -0
- quantum/core/parsers/jobs/job_parser.py +71 -0
- quantum/core/parsers/jobs/schedule_parser.py +62 -0
- quantum/core/parsers/jobs/thread_parser.py +57 -0
- quantum/core/parsers/messaging/__init__.py +17 -0
- quantum/core/parsers/messaging/message_ack_parser.py +30 -0
- quantum/core/parsers/messaging/message_nack_parser.py +30 -0
- quantum/core/parsers/messaging/message_parser.py +114 -0
- quantum/core/parsers/messaging/queue_parser.py +61 -0
- quantum/core/parsers/messaging/websocket_parser.py +121 -0
- quantum/core/parsers/routing/__init__.py +9 -0
- quantum/core/parsers/routing/route_parser.py +41 -0
- quantum/core/parsers/scripting/__init__.py +12 -0
- quantum/core/parsers/scripting/pyclass_parser.py +62 -0
- quantum/core/parsers/scripting/pydecorator_parser.py +68 -0
- quantum/core/parsers/scripting/pyimport_parser.py +52 -0
- quantum/core/parsers/scripting/python_parser.py +49 -0
- quantum/core/parsers/services/__init__.py +12 -0
- quantum/core/parsers/services/dump_parser.py +52 -0
- quantum/core/parsers/services/file_parser.py +48 -0
- quantum/core/parsers/services/log_parser.py +46 -0
- quantum/core/parsers/services/mail_parser.py +65 -0
- quantum/core/tiers.py +164 -0
- quantum/core/xml_lines.py +81 -0
- quantum/packages/__init__.py +28 -0
- quantum/packages/manager.py +413 -0
- quantum/packages/manifest.py +351 -0
- quantum/packages/registry.py +399 -0
- quantum/packages/resolver.py +336 -0
- quantum/plugins/__init__.py +33 -0
- quantum/plugins/hooks.py +329 -0
- quantum/plugins/loader.py +479 -0
- quantum/plugins/manifest.py +336 -0
- quantum/plugins/registry.py +371 -0
- quantum/runtime/__init__.py +25 -0
- quantum/runtime/action_handler.py +532 -0
- quantum/runtime/adapters/__init__.py +88 -0
- quantum/runtime/adapters/memory_adapter.py +690 -0
- quantum/runtime/adapters/rabbitmq_adapter.py +715 -0
- quantum/runtime/adapters/redis_adapter.py +582 -0
- quantum/runtime/adapters/sqlite_adapter.py +414 -0
- quantum/runtime/agent_service.py +1133 -0
- quantum/runtime/ast_cache.py +506 -0
- quantum/runtime/auth_service.py +267 -0
- quantum/runtime/component.py +1048 -0
- quantum/runtime/component_composer.py +133 -0
- quantum/runtime/component_resolver.py +174 -0
- quantum/runtime/conditions.py +54 -0
- quantum/runtime/database_service.py +595 -0
- quantum/runtime/db_schema.py +100 -0
- quantum/runtime/dev_panel.py +178 -0
- quantum/runtime/email_service.py +162 -0
- quantum/runtime/error_handler.py +295 -0
- quantum/runtime/execution_context.py +283 -0
- quantum/runtime/executor_registry.py +178 -0
- quantum/runtime/executors/__init__.py +71 -0
- quantum/runtime/executors/ai/__init__.py +12 -0
- quantum/runtime/executors/ai/agent_executor.py +217 -0
- quantum/runtime/executors/ai/knowledge_executor.py +114 -0
- quantum/runtime/executors/ai/llm_executor.py +153 -0
- quantum/runtime/executors/ai/team_executor.py +171 -0
- quantum/runtime/executors/base.py +264 -0
- quantum/runtime/executors/control_flow/__init__.py +12 -0
- quantum/runtime/executors/control_flow/if_executor.py +98 -0
- quantum/runtime/executors/control_flow/loop_executor.py +308 -0
- quantum/runtime/executors/control_flow/redirect_executor.py +43 -0
- quantum/runtime/executors/control_flow/set_executor.py +464 -0
- quantum/runtime/executors/data/__init__.py +12 -0
- quantum/runtime/executors/data/data_executor.py +156 -0
- quantum/runtime/executors/data/invoke_executor.py +228 -0
- quantum/runtime/executors/data/query_executor.py +290 -0
- quantum/runtime/executors/data/transaction_executor.py +91 -0
- quantum/runtime/executors/jobs/__init__.py +11 -0
- quantum/runtime/executors/jobs/job_executor.py +190 -0
- quantum/runtime/executors/jobs/schedule_executor.py +132 -0
- quantum/runtime/executors/jobs/thread_executor.py +127 -0
- quantum/runtime/executors/messaging/__init__.py +17 -0
- quantum/runtime/executors/messaging/message_ack_executor.py +51 -0
- quantum/runtime/executors/messaging/message_executor.py +174 -0
- quantum/runtime/executors/messaging/queue_executor.py +103 -0
- quantum/runtime/executors/messaging/websocket_executor.py +197 -0
- quantum/runtime/executors/scripting/__init__.py +11 -0
- quantum/runtime/executors/scripting/pyclass_executor.py +90 -0
- quantum/runtime/executors/scripting/pyimport_executor.py +81 -0
- quantum/runtime/executors/scripting/python_executor.py +249 -0
- quantum/runtime/executors/services/__init__.py +12 -0
- quantum/runtime/executors/services/dump_executor.py +72 -0
- quantum/runtime/executors/services/file_executor.py +89 -0
- quantum/runtime/executors/services/log_executor.py +77 -0
- quantum/runtime/executors/services/mail_executor.py +81 -0
- quantum/runtime/expression_cache.py +498 -0
- quantum/runtime/file_upload_service.py +326 -0
- quantum/runtime/function_registry.py +118 -0
- quantum/runtime/game_builder.py +166 -0
- quantum/runtime/game_code_generator.py +2371 -0
- quantum/runtime/game_templates.py +2006 -0
- quantum/runtime/godot_code_generator.py +4681 -0
- quantum/runtime/godot_templates.py +1449 -0
- quantum/runtime/job_executor.py +1599 -0
- quantum/runtime/knowledge_service.py +546 -0
- quantum/runtime/llm_cache.py +100 -0
- quantum/runtime/llm_providers.py +704 -0
- quantum/runtime/llm_service.py +287 -0
- quantum/runtime/local_server.py +28 -0
- quantum/runtime/logging_setup.py +141 -0
- quantum/runtime/message_broker.py +364 -0
- quantum/runtime/message_queue_service.py +571 -0
- quantum/runtime/param_validation.py +218 -0
- quantum/runtime/pypy_compat.py +317 -0
- quantum/runtime/python_bridge.py +698 -0
- quantum/runtime/query_validators.py +304 -0
- quantum/runtime/renderer.py +734 -0
- quantum/runtime/service_container.py +470 -0
- quantum/runtime/table_params.py +163 -0
- quantum/runtime/terminal_builder.py +76 -0
- quantum/runtime/terminal_code_generator.py +607 -0
- quantum/runtime/terminal_templates.py +243 -0
- quantum/runtime/testing_builder.py +77 -0
- quantum/runtime/testing_code_generator.py +833 -0
- quantum/runtime/testing_templates.py +85 -0
- quantum/runtime/ui_builder.py +222 -0
- quantum/runtime/ui_console.py +405 -0
- quantum/runtime/ui_desktop.py +56 -0
- quantum/runtime/ui_form_rules.py +193 -0
- quantum/runtime/ui_html_adapter.py +2567 -0
- quantum/runtime/ui_html_templates.py +2106 -0
- quantum/runtime/ui_mobile_adapter.py +1832 -0
- quantum/runtime/ui_mobile_templates.py +1003 -0
- quantum/runtime/ui_page_renderer.py +392 -0
- quantum/runtime/ui_pager.py +73 -0
- quantum/runtime/ui_table_edit.py +139 -0
- quantum/runtime/ui_textual_adapter.py +1866 -0
- quantum/runtime/ui_textual_templates.py +45 -0
- quantum/runtime/ui_tokens.py +465 -0
- quantum/runtime/ui_validator.py +365 -0
- quantum/runtime/ui_view.py +221 -0
- quantum/runtime/validators.py +256 -0
- quantum/runtime/web_server.py +2131 -0
- quantum/runtime/websocket_adapter.py +501 -0
- quantum/runtime/websocket_service.py +585 -0
- quantum/runtime/websocket_transport.py +289 -0
- quantum/runtime/wsgi.py +101 -0
- quantum/services.py +109 -0
- quantum/utils/__init__.py +1 -0
- quantum_admin/__init__.py +4 -0
- quantum_admin/assets/quantum-admin-connectors.js +123 -0
- quantum_admin/assets/quantum-admin.css +2058 -0
- quantum_admin/assets/quantum-source-highlight.js +106 -0
- quantum_admin/backend/__init__.py +4 -0
- quantum_admin/backend/audit_service.py +346 -0
- quantum_admin/backend/auth_service.py +394 -0
- quantum_admin/backend/component_discovery.py +766 -0
- quantum_admin/backend/config_generator.py +586 -0
- quantum_admin/backend/connector_service.py +1016 -0
- quantum_admin/backend/crud.py +557 -0
- quantum_admin/backend/database.py +226 -0
- quantum_admin/backend/db_setup_service.py +193 -0
- quantum_admin/backend/deploy_service.py +698 -0
- quantum_admin/backend/docker_service.py +422 -0
- quantum_admin/backend/environment_service.py +418 -0
- quantum_admin/backend/git_service.py +370 -0
- quantum_admin/backend/health_service.py +390 -0
- quantum_admin/backend/job_service.py +347 -0
- quantum_admin/backend/log_service.py +331 -0
- quantum_admin/backend/main.py +14426 -0
- quantum_admin/backend/models.py +986 -0
- quantum_admin/backend/pipeline_service.py +812 -0
- quantum_admin/backend/resource_manager.py +1118 -0
- quantum_admin/backend/schemas.py +419 -0
- quantum_admin/backend/secret_manager.py +277 -0
- quantum_admin/backend/settings_service.py +488 -0
- quantum_admin/backend/template_service.py +710 -0
- quantum_admin/backend/test_execution_service.py +364 -0
- quantum_admin/backend/test_generator.py +782 -0
- quantum_admin/backend/webhook_service.py +454 -0
- quantum_admin/backend/websocket_manager.py +360 -0
- quantum_admin/components/admin/_layout/AdminShell.q +121 -0
- quantum_admin/components/admin/agents.q +107 -0
- quantum_admin/components/admin/app/[name].q +558 -0
- quantum_admin/components/admin/applications.q +160 -0
- quantum_admin/components/admin/component/[...path].q +205 -0
- quantum_admin/components/admin/components.q +59 -0
- quantum_admin/components/admin/connectors.q +283 -0
- quantum_admin/components/admin/dashboard.q +86 -0
- quantum_admin/components/admin/database.q +95 -0
- quantum_admin/components/admin/features.q +69 -0
- quantum_admin/components/admin/index.q +12 -0
- quantum_admin/components/admin/jobs.q +75 -0
- quantum_admin/components/admin/login.q +65 -0
- quantum_admin/components/admin/logout.q +11 -0
- quantum_admin/components/admin/settings.q +174 -0
- quantum_admin/components/admin/source.q +45 -0
- quantum_admin/components/admin/tests.q +73 -0
- quantum_admin/run.py +13 -0
- quantum_admin/services/__init__.py +16 -0
- quantum_admin/services/_base.py +84 -0
- quantum_admin/services/_component_test_generator.py +205 -0
- quantum_admin/services/_yaml_editor.py +82 -0
- quantum_admin/services/apps.py +330 -0
- quantum_admin/services/auth.py +61 -0
- quantum_admin/services/components.py +210 -0
- quantum_admin/services/connectors.py +164 -0
- quantum_admin/services/projects.py +189 -0
- quantum_admin/services/repository.py +223 -0
- quantum_admin/services/settings.py +150 -0
- quantum_admin/services/yaml_import.py +118 -0
- quantum_framework-0.18.0.dist-info/METADATA +281 -0
- quantum_framework-0.18.0.dist-info/RECORD +333 -0
- quantum_framework-0.18.0.dist-info/WHEEL +5 -0
- quantum_framework-0.18.0.dist-info/entry_points.txt +2 -0
- quantum_framework-0.18.0.dist-info/licenses/LICENSE +21 -0
- quantum_framework-0.18.0.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""
|
|
2
|
+
UI Engine - Textual Templates
|
|
3
|
+
|
|
4
|
+
Provides:
|
|
5
|
+
- PyBuilder reuse from terminal_templates
|
|
6
|
+
- UI_TEXTUAL_APP_TEMPLATE: Textual app template for UI engine
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from quantum.runtime.terminal_templates import PyBuilder, py_string, py_id, py_bool
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# ==========================================================================
|
|
13
|
+
# Textual App Template
|
|
14
|
+
# ==========================================================================
|
|
15
|
+
|
|
16
|
+
UI_TEXTUAL_APP_TEMPLATE = '''\
|
|
17
|
+
"""Quantum UI App - Generated Textual Application"""
|
|
18
|
+
|
|
19
|
+
from textual.app import App, ComposeResult
|
|
20
|
+
from textual.containers import Horizontal, Vertical, Grid, ScrollableContainer
|
|
21
|
+
from textual.widgets import (
|
|
22
|
+
Header, Footer, Static, Button, Input, DataTable,
|
|
23
|
+
Checkbox, Switch, ProgressBar, Tree, RichLog, Rule,
|
|
24
|
+
LoadingIndicator, Markdown, TabbedContent, TabPane,
|
|
25
|
+
Collapsible, OptionList, Select, Label,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
{extra_imports}
|
|
29
|
+
|
|
30
|
+
class QuantumUIApp(App):
|
|
31
|
+
"""Quantum UI Application"""
|
|
32
|
+
|
|
33
|
+
TITLE = {title}
|
|
34
|
+
CSS = """{css}"""
|
|
35
|
+
|
|
36
|
+
{bindings}
|
|
37
|
+
def compose(self) -> ComposeResult:
|
|
38
|
+
{compose_body}
|
|
39
|
+
|
|
40
|
+
{methods}
|
|
41
|
+
|
|
42
|
+
if __name__ == "__main__":
|
|
43
|
+
app = QuantumUIApp()
|
|
44
|
+
app.run()
|
|
45
|
+
'''
|
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
"""
|
|
2
|
+
UI Engine - Design Tokens System
|
|
3
|
+
|
|
4
|
+
Provides a normalized design system that works across HTML and Textual targets.
|
|
5
|
+
Tokens ensure visual consistency when the same UI definition is rendered
|
|
6
|
+
in different environments.
|
|
7
|
+
|
|
8
|
+
Token Categories:
|
|
9
|
+
- Spacing: xs, sm, md, lg, xl (padding, margin, gap)
|
|
10
|
+
- Sizing: auto, fill, 1/2, 1/3, 1/4, 2/3, 3/4
|
|
11
|
+
- Colors: semantic (primary, secondary, success, danger, warning, info)
|
|
12
|
+
- Typography: xs, sm, md, lg, xl, 2xl
|
|
13
|
+
|
|
14
|
+
Usage:
|
|
15
|
+
from quantum.runtime.ui_tokens import TokenConverter
|
|
16
|
+
|
|
17
|
+
html_converter = TokenConverter('html')
|
|
18
|
+
textual_converter = TokenConverter('textual')
|
|
19
|
+
|
|
20
|
+
html_converter.spacing('md') # -> '16px'
|
|
21
|
+
textual_converter.spacing('md') # -> '2'
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from typing import Dict, Optional, Tuple
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# ==========================================================================
|
|
28
|
+
# Spacing Tokens
|
|
29
|
+
# ==========================================================================
|
|
30
|
+
|
|
31
|
+
# Spacing in abstract units (converted per-target)
|
|
32
|
+
SPACING_TOKENS = {
|
|
33
|
+
'none': 0,
|
|
34
|
+
'xs': 4,
|
|
35
|
+
'sm': 8,
|
|
36
|
+
'md': 16,
|
|
37
|
+
'lg': 24,
|
|
38
|
+
'xl': 32,
|
|
39
|
+
'2xl': 48,
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
# HTML: pixels
|
|
43
|
+
SPACING_HTML = {k: f"{v}px" for k, v in SPACING_TOKENS.items()}
|
|
44
|
+
SPACING_HTML['none'] = '0'
|
|
45
|
+
|
|
46
|
+
# Textual: character cells (roughly 8px per cell)
|
|
47
|
+
SPACING_TEXTUAL = {
|
|
48
|
+
'none': '0',
|
|
49
|
+
'xs': '1',
|
|
50
|
+
'sm': '1',
|
|
51
|
+
'md': '2',
|
|
52
|
+
'lg': '3',
|
|
53
|
+
'xl': '4',
|
|
54
|
+
'2xl': '6',
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
# ==========================================================================
|
|
59
|
+
# Sizing Tokens
|
|
60
|
+
# ==========================================================================
|
|
61
|
+
|
|
62
|
+
SIZE_TOKENS = {
|
|
63
|
+
'auto': 'auto',
|
|
64
|
+
'fill': 'full',
|
|
65
|
+
'1/2': '50%',
|
|
66
|
+
'1/3': '33.333%',
|
|
67
|
+
'1/4': '25%',
|
|
68
|
+
'2/3': '66.666%',
|
|
69
|
+
'3/4': '75%',
|
|
70
|
+
'full': '100%',
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
# HTML sizing
|
|
74
|
+
SIZE_HTML = {
|
|
75
|
+
'auto': 'auto',
|
|
76
|
+
'fill': '100%',
|
|
77
|
+
'full': '100%',
|
|
78
|
+
'1/2': '50%',
|
|
79
|
+
'1/3': '33.333%',
|
|
80
|
+
'1/4': '25%',
|
|
81
|
+
'2/3': '66.666%',
|
|
82
|
+
'3/4': '75%',
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
# Textual sizing (uses fr units or %)
|
|
86
|
+
SIZE_TEXTUAL = {
|
|
87
|
+
'auto': 'auto',
|
|
88
|
+
'fill': '1fr',
|
|
89
|
+
'full': '100%',
|
|
90
|
+
'1/2': '1fr', # In a 2-column context
|
|
91
|
+
'1/3': '1fr', # In a 3-column context
|
|
92
|
+
'1/4': '1fr', # In a 4-column context
|
|
93
|
+
'2/3': '2fr',
|
|
94
|
+
'3/4': '3fr',
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
# ==========================================================================
|
|
99
|
+
# Color Tokens
|
|
100
|
+
# ==========================================================================
|
|
101
|
+
|
|
102
|
+
# Semantic color names
|
|
103
|
+
COLOR_SEMANTIC = {
|
|
104
|
+
'primary', 'secondary', 'success', 'danger',
|
|
105
|
+
'warning', 'info', 'light', 'dark',
|
|
106
|
+
'text', 'background', 'border', 'muted',
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
# HTML: CSS custom properties
|
|
110
|
+
COLOR_HTML = {
|
|
111
|
+
'primary': 'var(--q-primary)',
|
|
112
|
+
'secondary': 'var(--q-secondary)',
|
|
113
|
+
'success': 'var(--q-success)',
|
|
114
|
+
'danger': 'var(--q-danger)',
|
|
115
|
+
'warning': 'var(--q-warning)',
|
|
116
|
+
'info': 'var(--q-info)',
|
|
117
|
+
'light': 'var(--q-light)',
|
|
118
|
+
'dark': 'var(--q-dark)',
|
|
119
|
+
'text': 'var(--q-text)',
|
|
120
|
+
'background': 'var(--q-bg)',
|
|
121
|
+
'border': 'var(--q-border)',
|
|
122
|
+
'muted': 'var(--q-secondary)',
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
# Textual: theme variables ($ prefix)
|
|
126
|
+
COLOR_TEXTUAL = {
|
|
127
|
+
'primary': '$primary',
|
|
128
|
+
'secondary': '$secondary',
|
|
129
|
+
'success': '$success',
|
|
130
|
+
'danger': '$error',
|
|
131
|
+
'warning': '$warning',
|
|
132
|
+
'info': '$accent',
|
|
133
|
+
'light': '$surface',
|
|
134
|
+
'dark': '$background',
|
|
135
|
+
'text': '$text',
|
|
136
|
+
'background': '$background',
|
|
137
|
+
'border': '$primary-background',
|
|
138
|
+
'muted': '$text-muted',
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
# ==========================================================================
|
|
143
|
+
# Typography Tokens
|
|
144
|
+
# ==========================================================================
|
|
145
|
+
|
|
146
|
+
FONT_SIZE_TOKENS = {
|
|
147
|
+
'xs': 0.75, # 12px
|
|
148
|
+
'sm': 0.875, # 14px
|
|
149
|
+
'md': 1.0, # 16px
|
|
150
|
+
'lg': 1.25, # 20px
|
|
151
|
+
'xl': 1.5, # 24px
|
|
152
|
+
'2xl': 2.0, # 32px
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
FONT_SIZE_HTML = {
|
|
156
|
+
'xs': 'var(--q-font-xs)',
|
|
157
|
+
'sm': 'var(--q-font-sm)',
|
|
158
|
+
'md': 'var(--q-font-md)',
|
|
159
|
+
'lg': 'var(--q-font-lg)',
|
|
160
|
+
'xl': 'var(--q-font-xl)',
|
|
161
|
+
'2xl': 'var(--q-font-2xl)',
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
# Textual doesn't support font sizes in the same way
|
|
165
|
+
# We use text styles instead
|
|
166
|
+
FONT_SIZE_TEXTUAL = {
|
|
167
|
+
'xs': '', # No direct mapping
|
|
168
|
+
'sm': '', # No direct mapping
|
|
169
|
+
'md': '', # Default
|
|
170
|
+
'lg': 'bold', # Emphasize with bold
|
|
171
|
+
'xl': 'bold',
|
|
172
|
+
'2xl': 'bold',
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
# ==========================================================================
|
|
177
|
+
# Align/Justify Tokens
|
|
178
|
+
# ==========================================================================
|
|
179
|
+
|
|
180
|
+
ALIGN_TOKENS = {'start', 'center', 'end', 'stretch'}
|
|
181
|
+
|
|
182
|
+
ALIGN_HTML = {
|
|
183
|
+
'start': 'flex-start',
|
|
184
|
+
'center': 'center',
|
|
185
|
+
'end': 'flex-end',
|
|
186
|
+
'stretch': 'stretch',
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
# Textual uses different alignment syntax: "horizontal vertical"
|
|
190
|
+
ALIGN_TEXTUAL = {
|
|
191
|
+
'start': 'left',
|
|
192
|
+
'center': 'center',
|
|
193
|
+
'end': 'right',
|
|
194
|
+
'stretch': 'center', # No direct equivalent
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
JUSTIFY_TOKENS = {'start', 'center', 'end', 'between', 'around'}
|
|
198
|
+
|
|
199
|
+
JUSTIFY_HTML = {
|
|
200
|
+
'start': 'flex-start',
|
|
201
|
+
'center': 'center',
|
|
202
|
+
'end': 'flex-end',
|
|
203
|
+
'between': 'space-between',
|
|
204
|
+
'around': 'space-around',
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
# Textual doesn't have justify-content equivalent
|
|
208
|
+
# We approximate with alignment
|
|
209
|
+
JUSTIFY_TEXTUAL = {
|
|
210
|
+
'start': 'left',
|
|
211
|
+
'center': 'center',
|
|
212
|
+
'end': 'right',
|
|
213
|
+
'between': 'center', # No equivalent, use center
|
|
214
|
+
'around': 'center', # No equivalent, use center
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
# ==========================================================================
|
|
219
|
+
# Token Converter
|
|
220
|
+
# ==========================================================================
|
|
221
|
+
|
|
222
|
+
class TokenConverter:
|
|
223
|
+
"""Converts design tokens to target-specific values."""
|
|
224
|
+
|
|
225
|
+
def __init__(self, target: str = 'html'):
|
|
226
|
+
"""
|
|
227
|
+
Args:
|
|
228
|
+
target: 'html' or 'textual'
|
|
229
|
+
"""
|
|
230
|
+
self.target = target.lower()
|
|
231
|
+
if self.target not in ('html', 'textual'):
|
|
232
|
+
raise ValueError(f"Unknown target: {target}")
|
|
233
|
+
|
|
234
|
+
def spacing(self, value: str) -> str:
|
|
235
|
+
"""Convert spacing token or raw value to target format.
|
|
236
|
+
|
|
237
|
+
Accepts:
|
|
238
|
+
- Token: 'sm', 'md', 'lg', etc.
|
|
239
|
+
- Raw pixel: '16', '16px'
|
|
240
|
+
- Raw percentage: '10%'
|
|
241
|
+
"""
|
|
242
|
+
if not value:
|
|
243
|
+
return ''
|
|
244
|
+
|
|
245
|
+
value_lower = value.lower().strip()
|
|
246
|
+
|
|
247
|
+
# Check if it's a token
|
|
248
|
+
if value_lower in SPACING_TOKENS:
|
|
249
|
+
if self.target == 'html':
|
|
250
|
+
return SPACING_HTML[value_lower]
|
|
251
|
+
else:
|
|
252
|
+
return SPACING_TEXTUAL[value_lower]
|
|
253
|
+
|
|
254
|
+
# Raw value - convert for target
|
|
255
|
+
return self._convert_raw_spacing(value)
|
|
256
|
+
|
|
257
|
+
def _convert_raw_spacing(self, value: str) -> str:
|
|
258
|
+
"""Convert raw spacing value to target format."""
|
|
259
|
+
if self.target == 'html':
|
|
260
|
+
# HTML accepts px, %, em, etc.
|
|
261
|
+
if value.endswith(('px', '%', 'em', 'rem')):
|
|
262
|
+
return value
|
|
263
|
+
try:
|
|
264
|
+
int(value)
|
|
265
|
+
return f"{value}px"
|
|
266
|
+
except ValueError:
|
|
267
|
+
return value
|
|
268
|
+
else:
|
|
269
|
+
# Textual uses character cells
|
|
270
|
+
if value.endswith('px'):
|
|
271
|
+
px = int(value[:-2])
|
|
272
|
+
return str(max(1, px // 8))
|
|
273
|
+
if value.endswith('%'):
|
|
274
|
+
return value # Textual supports %
|
|
275
|
+
try:
|
|
276
|
+
px = int(value)
|
|
277
|
+
return str(max(1, px // 8))
|
|
278
|
+
except ValueError:
|
|
279
|
+
return '1' # Default to 1 cell
|
|
280
|
+
|
|
281
|
+
def size(self, value: str) -> str:
|
|
282
|
+
"""Convert size token or raw value to target format.
|
|
283
|
+
|
|
284
|
+
Accepts:
|
|
285
|
+
- Token: 'fill', 'auto', '1/2', '1/3', etc.
|
|
286
|
+
- Raw pixel: '200', '200px'
|
|
287
|
+
- Raw percentage: '50%'
|
|
288
|
+
"""
|
|
289
|
+
if not value:
|
|
290
|
+
return ''
|
|
291
|
+
|
|
292
|
+
value_lower = value.lower().strip()
|
|
293
|
+
|
|
294
|
+
# Check if it's a token
|
|
295
|
+
if value_lower in SIZE_TOKENS:
|
|
296
|
+
if self.target == 'html':
|
|
297
|
+
return SIZE_HTML.get(value_lower, value)
|
|
298
|
+
else:
|
|
299
|
+
return SIZE_TEXTUAL.get(value_lower, value)
|
|
300
|
+
|
|
301
|
+
# Raw value
|
|
302
|
+
return self._convert_raw_size(value)
|
|
303
|
+
|
|
304
|
+
def _convert_raw_size(self, value: str) -> str:
|
|
305
|
+
"""Convert raw size value to target format."""
|
|
306
|
+
if self.target == 'html':
|
|
307
|
+
if value == 'fill':
|
|
308
|
+
return '100%'
|
|
309
|
+
if value.endswith(('px', '%', 'em', 'rem', 'vw', 'vh')):
|
|
310
|
+
return value
|
|
311
|
+
try:
|
|
312
|
+
int(value)
|
|
313
|
+
return f"{value}px"
|
|
314
|
+
except ValueError:
|
|
315
|
+
return value
|
|
316
|
+
else:
|
|
317
|
+
# Textual
|
|
318
|
+
if value == 'fill':
|
|
319
|
+
return '100%'
|
|
320
|
+
if value.endswith('%'):
|
|
321
|
+
return value
|
|
322
|
+
if value.endswith('px'):
|
|
323
|
+
px = int(value[:-2])
|
|
324
|
+
return str(max(1, px // 8)) # Convert to cells
|
|
325
|
+
try:
|
|
326
|
+
px = int(value)
|
|
327
|
+
return str(max(1, px // 8))
|
|
328
|
+
except ValueError:
|
|
329
|
+
return 'auto'
|
|
330
|
+
|
|
331
|
+
def color(self, value: str) -> str:
|
|
332
|
+
"""Convert color token or raw value to target format.
|
|
333
|
+
|
|
334
|
+
Accepts:
|
|
335
|
+
- Token: 'primary', 'success', etc.
|
|
336
|
+
- Raw hex: '#ff0000'
|
|
337
|
+
- Raw name: 'red', 'blue'
|
|
338
|
+
"""
|
|
339
|
+
if not value:
|
|
340
|
+
return ''
|
|
341
|
+
|
|
342
|
+
value_lower = value.lower().strip()
|
|
343
|
+
|
|
344
|
+
# Check if it's a semantic token
|
|
345
|
+
if value_lower in COLOR_SEMANTIC:
|
|
346
|
+
if self.target == 'html':
|
|
347
|
+
return COLOR_HTML.get(value_lower, value)
|
|
348
|
+
else:
|
|
349
|
+
return COLOR_TEXTUAL.get(value_lower, value)
|
|
350
|
+
|
|
351
|
+
# Raw color value
|
|
352
|
+
if self.target == 'html':
|
|
353
|
+
return value # HTML accepts any CSS color
|
|
354
|
+
else:
|
|
355
|
+
# Textual accepts color names and some formats
|
|
356
|
+
return self._convert_raw_color_textual(value)
|
|
357
|
+
|
|
358
|
+
def _convert_raw_color_textual(self, value: str) -> str:
|
|
359
|
+
"""Convert raw color for Textual."""
|
|
360
|
+
# Textual supports: color names, rgb(), ansi colors
|
|
361
|
+
if value.startswith('#'):
|
|
362
|
+
# Convert hex to rgb for better compatibility
|
|
363
|
+
return value # Textual 0.40+ supports hex
|
|
364
|
+
return value
|
|
365
|
+
|
|
366
|
+
def font_size(self, value: str) -> str:
|
|
367
|
+
"""Convert font size token to target format."""
|
|
368
|
+
if not value:
|
|
369
|
+
return ''
|
|
370
|
+
|
|
371
|
+
value_lower = value.lower().strip()
|
|
372
|
+
|
|
373
|
+
if value_lower in FONT_SIZE_TOKENS:
|
|
374
|
+
if self.target == 'html':
|
|
375
|
+
return FONT_SIZE_HTML.get(value_lower, value)
|
|
376
|
+
else:
|
|
377
|
+
return FONT_SIZE_TEXTUAL.get(value_lower, '')
|
|
378
|
+
|
|
379
|
+
# Raw value
|
|
380
|
+
return value if self.target == 'html' else ''
|
|
381
|
+
|
|
382
|
+
def align(self, value: str) -> str:
|
|
383
|
+
"""Convert align token to target format."""
|
|
384
|
+
if not value:
|
|
385
|
+
return ''
|
|
386
|
+
|
|
387
|
+
value_lower = value.lower().strip()
|
|
388
|
+
|
|
389
|
+
if self.target == 'html':
|
|
390
|
+
return ALIGN_HTML.get(value_lower, value)
|
|
391
|
+
else:
|
|
392
|
+
return ALIGN_TEXTUAL.get(value_lower, 'center')
|
|
393
|
+
|
|
394
|
+
def justify(self, value: str) -> str:
|
|
395
|
+
"""Convert justify token to target format."""
|
|
396
|
+
if not value:
|
|
397
|
+
return ''
|
|
398
|
+
|
|
399
|
+
value_lower = value.lower().strip()
|
|
400
|
+
|
|
401
|
+
if self.target == 'html':
|
|
402
|
+
return JUSTIFY_HTML.get(value_lower, value)
|
|
403
|
+
else:
|
|
404
|
+
return JUSTIFY_TEXTUAL.get(value_lower, 'center')
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
# ==========================================================================
|
|
408
|
+
# Compatibility Warnings
|
|
409
|
+
# ==========================================================================
|
|
410
|
+
|
|
411
|
+
# Features that don't translate well between targets
|
|
412
|
+
COMPATIBILITY_WARNINGS = {
|
|
413
|
+
'gap': {
|
|
414
|
+
'textual': "gap is not supported in Textual; using margin on children",
|
|
415
|
+
},
|
|
416
|
+
'justify_between': {
|
|
417
|
+
'textual': "justify='between' has no Textual equivalent; items will be centered",
|
|
418
|
+
},
|
|
419
|
+
'justify_around': {
|
|
420
|
+
'textual': "justify='around' has no Textual equivalent; items will be centered",
|
|
421
|
+
},
|
|
422
|
+
'image': {
|
|
423
|
+
'textual': "Images cannot be displayed in terminal; showing placeholder text",
|
|
424
|
+
},
|
|
425
|
+
'link_external': {
|
|
426
|
+
'textual': "External links are not clickable in terminal; showing as text",
|
|
427
|
+
},
|
|
428
|
+
'font_size': {
|
|
429
|
+
'textual': "Font sizes are not adjustable in terminal; using text weight instead",
|
|
430
|
+
},
|
|
431
|
+
'animation': {
|
|
432
|
+
'textual': "CSS animations are not supported in terminal",
|
|
433
|
+
},
|
|
434
|
+
'pixel_units': {
|
|
435
|
+
'textual': "Pixel values are converted to character cells (÷8)",
|
|
436
|
+
},
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
def get_compatibility_warnings(features_used: set, target: str) -> list:
|
|
441
|
+
"""Get list of compatibility warnings for features used."""
|
|
442
|
+
warnings = []
|
|
443
|
+
for feature in features_used:
|
|
444
|
+
if feature in COMPATIBILITY_WARNINGS:
|
|
445
|
+
warning = COMPATIBILITY_WARNINGS[feature].get(target)
|
|
446
|
+
if warning:
|
|
447
|
+
warnings.append(f"[{feature}] {warning}")
|
|
448
|
+
return warnings
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
# ==========================================================================
|
|
452
|
+
# Utility: Check if value is a token
|
|
453
|
+
# ==========================================================================
|
|
454
|
+
|
|
455
|
+
def is_spacing_token(value: str) -> bool:
|
|
456
|
+
return value.lower().strip() in SPACING_TOKENS
|
|
457
|
+
|
|
458
|
+
def is_size_token(value: str) -> bool:
|
|
459
|
+
return value.lower().strip() in SIZE_TOKENS
|
|
460
|
+
|
|
461
|
+
def is_color_token(value: str) -> bool:
|
|
462
|
+
return value.lower().strip() in COLOR_SEMANTIC
|
|
463
|
+
|
|
464
|
+
def is_font_token(value: str) -> bool:
|
|
465
|
+
return value.lower().strip() in FONT_SIZE_TOKENS
|