ai / backend /chunking /js_chunker.py
3v324v23's picture
agent
b4291bc
Raw
History Blame Contribute Delete
2.25 kB
import re
from pathlib import Path
from backend.database.schemas import Chunk
SYMBOL_RE = re.compile(
r"^\s*(export\s+default\s+|export\s+)?"
r"(async\s+)?(function\s+(?P<fn>\w+)|class\s+(?P<class>\w+)|"
r"const\s+(?P<const>\w+)\s*=\s*(async\s*)?(\([^)]*\)|\w+)\s*=>)",
)
def _language(path: Path) -> str:
return {
".js": "javascript",
".jsx": "javascript",
".ts": "typescript",
".tsx": "typescript",
}.get(path.suffix.lower(), "text")
def chunk_js_file(path: Path, repo_root: Path, repo_id: str) -> list[Chunk]:
text = path.read_text(encoding="utf-8", errors="ignore")
lines = text.splitlines()
rel = path.relative_to(repo_root).as_posix()
starts: list[tuple[int, str, str]] = []
import_lines = [i + 1 for i, line in enumerate(lines) if line.strip().startswith("import ")]
if import_lines:
starts.append((min(import_lines), "imports", "imports"))
for i, line in enumerate(lines, start=1):
match = SYMBOL_RE.match(line)
if match:
symbol = match.group("fn") or match.group("class") or match.group("const") or "anonymous"
kind = "class" if match.group("class") else "function"
starts.append((i, symbol, kind))
if not starts:
return [
Chunk(
id=f"{repo_id}:{rel}:1",
repo_id=repo_id,
path=rel,
language=_language(path),
start_line=1,
end_line=max(1, len(lines)),
content=text,
)
]
starts = sorted(set(starts), key=lambda item: item[0])
chunks: list[Chunk] = []
for idx, (start, symbol, kind) in enumerate(starts):
end = starts[idx + 1][0] - 1 if idx + 1 < len(starts) else len(lines)
chunks.append(
Chunk(
id=f"{repo_id}:{rel}:{start}:{symbol}",
repo_id=repo_id,
path=rel,
language=_language(path),
symbol=symbol,
kind=kind,
start_line=start,
end_line=max(start, end),
content="\n".join(lines[start - 1 : end]).strip(),
)
)
return chunks