create-caspian-app 1.3.1 → 1.3.2

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.
@@ -2,7 +2,7 @@
2
2
 
3
3
  A single-file component imports its children (`from .Dialog import
4
4
  DialogContent`) and then uses them **only** as `<x-dialog-content>` tags inside
5
- an `html(...)` / `render_html(...)` template string. Ruff parses Python, not the
5
+ an `html(...)` template string. Ruff parses Python, not the
6
6
  template, so it reports every such import as unused (F401). Those imports are
7
7
  load-bearing: casp resolves the tag from the module's globals at render time
8
8
  (`component_decorator._attach_caller_scope`).
@@ -76,8 +76,6 @@ async def _resolve_static_paths(route) -> list | None:
76
76
  - a list of scalars: [1, 2] (mapped onto the route's single param)
77
77
  - a callable (sync or async) returning either of the above
78
78
  """
79
- if not route.has_py:
80
- return None
81
79
  module = main.load_route_module(_route_py_path(route))
82
80
  provider = getattr(module, "static_paths", None)
83
81
  if provider is None:
@@ -143,6 +143,11 @@ SCRIPT_BLOCK = re.compile(r"<script\b.*?</script\s*>", re.IGNORECASE | re.DOTALL
143
143
  PRE_BLOCK = re.compile(r"<(pre|code)\b.*?</\1\s*>", re.IGNORECASE | re.DOTALL)
144
144
  HTML_COMMENT = re.compile(r"<!--.*?-->", re.DOTALL)
145
145
 
146
+ # Components are imported with Python imports; an `@import` HTML comment does
147
+ # not import anything and the compiler refuses it. Matched BEFORE comments are
148
+ # blanked out — the construct *is* a comment.
149
+ IMPORT_COMMENT = re.compile(r"<!--\s*@import\b")
150
+
146
151
  # In a single-file component the markup lives in a triple-quoted string handed to
147
152
  # `html(...)`. Surrounding Python must not be matched: `onValueChange=...` is an
148
153
  # ordinary keyword argument, and flagging it as a camelCase event prop would make
@@ -172,14 +177,19 @@ def _keep_only(text: str, pattern: re.Pattern[str]) -> str:
172
177
  return "".join(kept)
173
178
 
174
179
 
175
- def _markup_only(text: str, *, is_python: bool) -> str:
176
- """Reduce a source file to just the markup a template rule may match."""
180
+ def _markup_regions(text: str, *, is_python: bool) -> tuple[str, str]:
181
+ """Reduce a source file to just the markup a template rule may match.
182
+
183
+ Returns ``(markup, markup_with_comments)``: the first has HTML comments
184
+ blanked for the JSX/directive rules; the second keeps them so the
185
+ ``@import``-comment rule can still see its target.
186
+ """
177
187
  if is_python:
178
188
  # Only triple-quoted regions can hold markup in a single-file component.
179
189
  text = _keep_only(text, TRIPLE_QUOTED)
180
- for pattern in (SCRIPT_BLOCK, PRE_BLOCK, HTML_COMMENT):
190
+ for pattern in (SCRIPT_BLOCK, PRE_BLOCK):
181
191
  text = _blank_out(text, pattern)
182
- return text
192
+ return _blank_out(text, HTML_COMMENT), text
183
193
 
184
194
 
185
195
  def _position(text: str, offset: int) -> tuple[int, int]:
@@ -190,9 +200,24 @@ def _position(text: str, offset: int) -> tuple[int, int]:
190
200
 
191
201
  def lint_text(text: str, rel_path: str, *, is_python: bool = False) -> list[TemplateIssue]:
192
202
  """Return every template issue found in one file's contents."""
193
- markup = _markup_only(text, is_python=is_python)
203
+ markup, markup_with_comments = _markup_regions(text, is_python=is_python)
194
204
  issues: list[TemplateIssue] = []
195
205
 
206
+ for match in IMPORT_COMMENT.finditer(markup_with_comments):
207
+ line, column = _position(markup_with_comments, match.start())
208
+ issues.append(
209
+ TemplateIssue(
210
+ rel_path,
211
+ line,
212
+ column,
213
+ "import-comment",
214
+ "An '@import' HTML comment does not import a component. Import "
215
+ "it in the owning Python module "
216
+ "(from src.lib.maddex.Button import Button) and keep the "
217
+ "<x-button> tag in the markup.",
218
+ )
219
+ )
220
+
196
221
  for rule in RULES:
197
222
  for match in rule.pattern.finditer(markup):
198
223
  line, column = _position(markup, match.start())
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-caspian-app",
3
- "version": "1.3.1",
3
+ "version": "1.3.2",
4
4
  "description": "Scaffold a new Caspian project (FastAPI-powered reactive Python framework).",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",