tw-framework 0.2.3__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.
- tw_framework/__init__.py +13 -0
- tw_framework/advanced_diagnostics.py +25 -0
- tw_framework/asset_optimizer.py +30 -0
- tw_framework/ast_nodes.py +283 -0
- tw_framework/build.py +7 -0
- tw_framework/build_performance.py +26 -0
- tw_framework/build_report.py +84 -0
- tw_framework/cli.py +1258 -0
- tw_framework/code_splitting.py +76 -0
- tw_framework/common.py +22 -0
- tw_framework/compiler.py +4817 -0
- tw_framework/compiler_stats.py +51 -0
- tw_framework/dead_code.py +44 -0
- tw_framework/dependency_graph.py +91 -0
- tw_framework/deploy.py +7 -0
- tw_framework/dev.py +9 -0
- tw_framework/diagnostics.py +98 -0
- tw_framework/dynamic_imports.py +51 -0
- tw_framework/error_formatter.py +53 -0
- tw_framework/framework.py +3216 -0
- tw_framework/hydration.py +129 -0
- tw_framework/incremental_cache.py +53 -0
- tw_framework/interpreter.py +42 -0
- tw_framework/ir.py +171 -0
- tw_framework/lexer.py +52 -0
- tw_framework/lowering.py +68 -0
- tw_framework/parser.py +167 -0
- tw_framework/partial_rebuild.py +24 -0
- tw_framework/performance_analyzer.py +37 -0
- tw_framework/plugin_runtime.py +196 -0
- tw_framework/production_optimizer.py +82 -0
- tw_framework/reactivity.py +349 -0
- tw_framework/render_css.py +22 -0
- tw_framework/render_html.py +259 -0
- tw_framework/route_optimizer.py +40 -0
- tw_framework/router.py +7 -0
- tw_framework/runtime_model.py +23 -0
- tw_framework/runtime_values.py +31 -0
- tw_framework/semantic.py +162 -0
- tw_framework/server.py +532 -0
- tw_framework/signature.py +51 -0
- tw_framework/static_dynamic_auto.py +32 -0
- tw_framework/streaming.py +135 -0
- tw_framework/test_build_cli_pytest.py +1078 -0
- tw_framework/tree_shaking.py +48 -0
- tw_framework/twm_parser.py +274 -0
- tw_framework-0.2.3.dist-info/METADATA +8 -0
- tw_framework-0.2.3.dist-info/RECORD +51 -0
- tw_framework-0.2.3.dist-info/WHEEL +5 -0
- tw_framework-0.2.3.dist-info/entry_points.txt +2 -0
- tw_framework-0.2.3.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Automatic code splitting for TW Framework.
|
|
3
|
+
|
|
4
|
+
Generates separate JavaScript chunks for each page and shared runtime.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import hashlib
|
|
8
|
+
import json
|
|
9
|
+
import logging
|
|
10
|
+
import os
|
|
11
|
+
from typing import Dict, List, Optional
|
|
12
|
+
|
|
13
|
+
from . import compiler
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def generate_chunks(pages: List[dict], output_dir: str) -> Dict[str, str]:
|
|
19
|
+
"""Generate code-split chunks for each page and return a mapping of page path to chunk URL."""
|
|
20
|
+
chunk_map = {}
|
|
21
|
+
shared_runtime = _build_shared_runtime()
|
|
22
|
+
runtime_url = _write_chunk(shared_runtime, "runtime", output_dir)
|
|
23
|
+
chunk_map["__shared__"] = runtime_url
|
|
24
|
+
|
|
25
|
+
for page in pages:
|
|
26
|
+
page_path = page["path"]
|
|
27
|
+
page_js = _build_page_js(page)
|
|
28
|
+
if page_js:
|
|
29
|
+
chunk_name = _page_chunk_name(page_path)
|
|
30
|
+
chunk_url = _write_chunk(page_js, chunk_name, output_dir)
|
|
31
|
+
chunk_map[page_path] = chunk_url
|
|
32
|
+
return chunk_map
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _build_shared_runtime() -> str:
|
|
36
|
+
"""Build the shared runtime JavaScript that is loaded on every page."""
|
|
37
|
+
return """
|
|
38
|
+
window.__tw = window.__tw || {};
|
|
39
|
+
window.__tw.router = window.__tw.router || {};
|
|
40
|
+
window.__tw.router.goto = function(path) {
|
|
41
|
+
window.location.href = path;
|
|
42
|
+
};
|
|
43
|
+
window.__twInvoke = function(name, event) {
|
|
44
|
+
var fn = window.__tw[name];
|
|
45
|
+
if (typeof fn === 'function') return fn(event);
|
|
46
|
+
};
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _build_page_js(page: dict) -> Optional[str]:
|
|
51
|
+
"""Build the JavaScript for a single page (events, router, etc.)."""
|
|
52
|
+
# In a real implementation, this would extract event handlers and router calls
|
|
53
|
+
# from the compiled page AST. For now, return a minimal placeholder.
|
|
54
|
+
return None
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _page_chunk_name(page_path: str) -> str:
|
|
58
|
+
"""Generate a deterministic chunk name from the page path."""
|
|
59
|
+
normalized = page_path.replace(os.sep, "/").lstrip("/")
|
|
60
|
+
return normalized.replace("/", "_").replace(".", "_")
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _write_chunk(js_content: str, name: str, output_dir: str) -> str:
|
|
64
|
+
"""Write a JavaScript chunk to the output directory and return its URL."""
|
|
65
|
+
digest = hashlib.sha256(js_content.encode("utf-8")).hexdigest()[:12]
|
|
66
|
+
filename = f"{name}.{digest}.js"
|
|
67
|
+
chunk_dir = os.path.join(output_dir, "_tw", "chunks")
|
|
68
|
+
os.makedirs(chunk_dir, exist_ok=True)
|
|
69
|
+
chunk_path = os.path.join(chunk_dir, filename)
|
|
70
|
+
if not os.path.exists(chunk_path):
|
|
71
|
+
with open(chunk_path, "w", encoding="utf-8") as f:
|
|
72
|
+
f.write(js_content)
|
|
73
|
+
return f"/_tw/chunks/{filename}"
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
__all__ = ["generate_chunks"]
|
tw_framework/common.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import hashlib
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def content_hash(value, *, length=None):
|
|
6
|
+
if isinstance(value, str):
|
|
7
|
+
payload = value.encode("utf-8")
|
|
8
|
+
elif isinstance(value, bytes):
|
|
9
|
+
payload = value
|
|
10
|
+
else:
|
|
11
|
+
payload = str(value).encode("utf-8")
|
|
12
|
+
digest = hashlib.md5(payload).hexdigest()
|
|
13
|
+
if length is not None:
|
|
14
|
+
return digest[: max(0, int(length))]
|
|
15
|
+
return digest
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def log(message, level="info", file=None):
|
|
19
|
+
stream = file
|
|
20
|
+
if stream is None:
|
|
21
|
+
stream = sys.stderr if str(level).lower() in {"warning", "error"} else sys.stdout
|
|
22
|
+
print(message, file=stream)
|