tw-framework 0.2.4__tar.gz → 0.2.6__tar.gz

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.
Files changed (62) hide show
  1. {tw_framework-0.2.4 → tw_framework-0.2.6}/PKG-INFO +1 -1
  2. {tw_framework-0.2.4 → tw_framework-0.2.6}/pyproject.toml +1 -1
  3. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/compiler.py +21 -1
  4. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/framework.py +24 -10
  5. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework.egg-info/PKG-INFO +1 -1
  6. {tw_framework-0.2.4 → tw_framework-0.2.6}/README.md +0 -0
  7. {tw_framework-0.2.4 → tw_framework-0.2.6}/setup.cfg +0 -0
  8. {tw_framework-0.2.4 → tw_framework-0.2.6}/tests/test_deployment.py +0 -0
  9. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/__init__.py +0 -0
  10. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/adapters/__init__.py +0 -0
  11. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/adapters/cloudflare.py +0 -0
  12. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/adapters/netlify.py +0 -0
  13. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/adapters/vercel.py +0 -0
  14. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/adapters/vercel_functions.py +0 -0
  15. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/advanced_diagnostics.py +0 -0
  16. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/asset_optimizer.py +0 -0
  17. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/ast_nodes.py +0 -0
  18. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/build.py +0 -0
  19. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/build_performance.py +0 -0
  20. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/build_report.py +0 -0
  21. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/cli.py +0 -0
  22. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/code_splitting.py +0 -0
  23. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/common.py +0 -0
  24. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/compiler_stats.py +0 -0
  25. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/dead_code.py +0 -0
  26. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/dependency_graph.py +0 -0
  27. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/deploy.py +0 -0
  28. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/dev.py +0 -0
  29. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/diagnostics.py +0 -0
  30. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/dynamic_imports.py +0 -0
  31. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/error_formatter.py +0 -0
  32. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/hydration.py +0 -0
  33. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/incremental_cache.py +0 -0
  34. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/interpreter.py +0 -0
  35. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/ir.py +0 -0
  36. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/lexer.py +0 -0
  37. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/lowering.py +0 -0
  38. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/parser.py +0 -0
  39. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/partial_rebuild.py +0 -0
  40. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/performance_analyzer.py +0 -0
  41. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/plugin_runtime.py +0 -0
  42. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/production_optimizer.py +0 -0
  43. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/reactivity.py +0 -0
  44. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/render_css.py +0 -0
  45. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/render_html.py +0 -0
  46. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/route_optimizer.py +0 -0
  47. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/router.py +0 -0
  48. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/runtime_model.py +0 -0
  49. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/runtime_values.py +0 -0
  50. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/semantic.py +0 -0
  51. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/server.py +0 -0
  52. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/signature.py +0 -0
  53. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/static_dynamic_auto.py +0 -0
  54. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/streaming.py +0 -0
  55. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/test_build_cli_pytest.py +0 -0
  56. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/tree_shaking.py +0 -0
  57. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework/twm_parser.py +0 -0
  58. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework.egg-info/SOURCES.txt +0 -0
  59. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework.egg-info/dependency_links.txt +0 -0
  60. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework.egg-info/entry_points.txt +0 -0
  61. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework.egg-info/requires.txt +0 -0
  62. {tw_framework-0.2.4 → tw_framework-0.2.6}/tw_framework.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tw-framework
3
- Version: 0.2.4
3
+ Version: 0.2.6
4
4
  Summary: TW framework CLI with create, dev, build, and deploy commands
5
5
  Author: TW Framework
6
6
  Requires-Python: >=3.9
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "tw-framework"
7
- version = "0.2.4"
7
+ version = "0.2.6"
8
8
  description = "TW framework CLI with create, dev, build, and deploy commands"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -1136,7 +1136,22 @@ def tokenize(code, allow_inline_scripts=False):
1136
1136
  start_line, start_col = line, col
1137
1137
  word = []
1138
1138
  # Read until whitespace, braces, quotes, or common operators.
1139
- while i < n and (code[i] not in ' \t\r\n{}"\'' and code[i] not in ONE_CHAR_OPS):
1139
+ # Exception: a `-` surrounded by alnum chars on both sides is kept as
1140
+ # part of the word (kebab-case identifiers like `aria-label`,
1141
+ # `data-foo`), since HTML/ARIA attribute names rely on this.
1142
+ while i < n:
1143
+ ch = code[i]
1144
+ if ch in ' \t\r\n{}"\'' or ch in ONE_CHAR_OPS:
1145
+ if (
1146
+ ch == "-"
1147
+ and word
1148
+ and word[-1].isalnum()
1149
+ and i + 1 < n
1150
+ and code[i + 1].isalnum()
1151
+ ):
1152
+ word.append(advance_one())
1153
+ continue
1154
+ break
1140
1155
  word.append(advance_one())
1141
1156
  word = "".join(word)
1142
1157
  if not word:
@@ -1569,6 +1584,11 @@ def parse_literal_value(raw):
1569
1584
  if os.environ.get("TW_WARN_LITERAL_PARSE", "").strip().lower() in {"1", "true", "yes", "on"}:
1570
1585
  log(f"⚠️ Literal parse failed, treating as string: {raw!r}", level="warning")
1571
1586
  return raw
1587
+ if stripped.startswith('"') and stripped.endswith('"') and len(stripped) >= 2:
1588
+ try:
1589
+ return json.loads(stripped)
1590
+ except json.JSONDecodeError:
1591
+ return stripped[1:-1]
1572
1592
  return raw
1573
1593
 
1574
1594
 
@@ -605,6 +605,20 @@ def parse_value_token(tokens, i):
605
605
  return compiler.parse_literal_value(expr), j
606
606
 
607
607
 
608
+ def parse_single_value_token(tokens, i):
609
+ """Parse exactly one literal token (STRING or WORD), without consuming
610
+ the rest of the line. Needed for directives that carry more than one
611
+ value on the same line, e.g. `auth "cookie" "redirect"`."""
612
+ if i >= len(tokens):
613
+ raise RuntimeError("Expected value token")
614
+ tok = tokens[i]
615
+ if tok.type == "STRING":
616
+ return tok.value, i + 1
617
+ if tok.type == "WORD" and tok.value not in {"{", "}", "[", "]", "(", ")"}:
618
+ return compiler.parse_literal_value(tok.value), i + 1
619
+ raise RuntimeError("Expected value token")
620
+
621
+
608
622
  def parse_middleware_rules(project_root: str) -> List[dict]:
609
623
  source_path = next((path for path in middleware_file_candidates(project_root) if os.path.exists(path)), None)
610
624
  if not source_path:
@@ -890,16 +904,16 @@ def parse_middleware_rules(project_root: str) -> List[dict]:
890
904
  if i < len(tokens) and tokens[i].type == "BRACE" and tokens[i].value == "{":
891
905
  rule["auth_rule"], i = parse_auth_block(i)
892
906
  else:
893
- cookie_name, i = parse_value_token(tokens, i)
894
- redirect_to, i = parse_value_token(tokens, i)
907
+ cookie_name, i = parse_single_value_token(tokens, i)
908
+ redirect_to, i = parse_single_value_token(tokens, i)
895
909
  rule["auth"] = {"cookie": cookie_name, "redirect": redirect_to}
896
910
  elif key == "header":
897
- header_name, i = parse_value_token(tokens, i)
898
- header_value, i = parse_value_token(tokens, i)
911
+ header_name, i = parse_single_value_token(tokens, i)
912
+ header_value, i = parse_single_value_token(tokens, i)
899
913
  rule["headers"].append((str(header_name), str(header_value)))
900
914
  elif key == "cookie":
901
- cookie_name, i = parse_value_token(tokens, i)
902
- cookie_value, i = parse_value_token(tokens, i)
915
+ cookie_name, i = parse_single_value_token(tokens, i)
916
+ cookie_value, i = parse_single_value_token(tokens, i)
903
917
  rule["cookies"].append((str(cookie_name), str(cookie_value)))
904
918
  elif key == "rate_limit":
905
919
  rule["rate_limit"], i = parse_rate_limit_block(i)
@@ -1153,12 +1167,12 @@ def parse_api_route_file(tw_path: str) -> Dict[str, dict]:
1153
1167
  elif key in {"json", "text", "html", "redirect"}:
1154
1168
  spec[key], i = parse_value_token(tokens, i)
1155
1169
  elif key == "header":
1156
- header_name, i = parse_value_token(tokens, i)
1157
- header_value, i = parse_value_token(tokens, i)
1170
+ header_name, i = parse_single_value_token(tokens, i)
1171
+ header_value, i = parse_single_value_token(tokens, i)
1158
1172
  spec["headers"].append((header_name, header_value))
1159
1173
  elif key == "cookie":
1160
- cookie_name, i = parse_value_token(tokens, i)
1161
- cookie_value, i = parse_value_token(tokens, i)
1174
+ cookie_name, i = parse_single_value_token(tokens, i)
1175
+ cookie_value, i = parse_single_value_token(tokens, i)
1162
1176
  spec["cookies"].append((cookie_name, cookie_value))
1163
1177
  else:
1164
1178
  raise RuntimeError(f"Unsupported API key `{key}` in {tw_path}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tw-framework
3
- Version: 0.2.4
3
+ Version: 0.2.6
4
4
  Summary: TW framework CLI with create, dev, build, and deploy commands
5
5
  Author: TW Framework
6
6
  Requires-Python: >=3.9
File without changes
File without changes