Skip to content

Commit

Permalink
fix:regex to import names with dash properly (#302)
Browse files Browse the repository at this point in the history
  • Loading branch information
Anshgrover23 authored Nov 29, 2024
1 parent 7b3b1f6 commit 56aeaef
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 4 deletions.
13 changes: 9 additions & 4 deletions src/components/CodeEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { Decoration, hoverTooltip, keymap } from "@codemirror/view"
import { getImportsFromCode } from "@tscircuit/prompt-benchmarks/code-runner-utils"
import type { ATABootstrapConfig } from "@typescript/ata"
import { setupTypeAcquisition } from "@typescript/ata"
import { TSCI_PACKAGE_PATTERN } from "../lib/constants"
import {
createDefaultMapFromCDN,
createSystem,
Expand Down Expand Up @@ -224,7 +225,9 @@ export const CodeEditor = ({
const lineStart = line.from
const lineEnd = line.to
const lineText = view.state.sliceDoc(lineStart, lineEnd)
const matches = Array.from(lineText.matchAll(/@tsci\/[\w\-.]+/g))
const matches = Array.from(
lineText.matchAll(TSCI_PACKAGE_PATTERN),
)

for (const match of matches) {
if (match.index !== undefined) {
Expand Down Expand Up @@ -260,17 +263,19 @@ export const CodeEditor = ({
const lineEnd = line.to
const lineText = view.state.sliceDoc(lineStart, lineEnd)
const matches = Array.from(
lineText.matchAll(/@tsci\/[\w\-.]+/g),
lineText.matchAll(TSCI_PACKAGE_PATTERN),
)
for (const match of matches) {
if (match.index !== undefined) {
const start = lineStart + match.index
const end = start + match[0].length
if (pos >= start && pos <= end) {
const importName = match[0]
const [owner, name] = importName
// Handle potential dots and dashes in package names
const [owner, ...nameParts] = importName
.replace("@tsci/", "")
.split(".")
const name = nameParts.join(".")
window.open(`/${owner}/${name}`, "_blank")
return true
}
Expand All @@ -292,7 +297,7 @@ export const CodeEditor = ({
for (let pos = from; pos < to; ) {
const line = view.state.doc.lineAt(pos)
const lineText = line.text
const matches = lineText.matchAll(/@tsci\/[\w\-.]+/g)
const matches = lineText.matchAll(TSCI_PACKAGE_PATTERN)
for (const match of matches) {
if (match.index !== undefined) {
const start = line.from + match.index
Expand Down
65 changes: 65 additions & 0 deletions src/lib/__tests__/constants.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { describe, expect, test } from "bun:test"
import { TSCI_PACKAGE_PATTERN } from "../constants"

describe("TSCI_PACKAGE_PATTERN", () => {
// Test valid patterns
const validPackages = [
"@tsci/basic",
"@tsci/package-name",
"@tsci/multiple-dashes-here",
"@tsci/package.subpackage",
"@tsci/complex-package.complex-subpackage",
"@tsci/a.b.c",
"@tsci/package-with-numbers123",
"@tsci/package123-with-numbers",
"@tsci/core.utils-helper",
"@tsci/double--dash",
]

validPackages.forEach((pkg) => {
test(`should match valid package: ${pkg}`, () => {
const matches = Array.from(pkg.matchAll(TSCI_PACKAGE_PATTERN))
expect(matches).toHaveLength(1)
expect(matches[0][0]).toBe(pkg)
})
})

// Test invalid patterns
const invalidPackages = [
"@tsci/", // Empty
"@tsci/123start-with-number", // Starts with number
"@tsci/-start-with-dash", // Starts with dash
"@tsci/.start-with-dot", // Starts with dot

"@tsci/double..dot", // Double dot
"@tsci/end-with-dash-", // Ends with dash
"@tsci/end-with-dot.", // Ends with dot
"@tsci/invalid@chars", // Invalid characters
"@tsci/dot.dash.-mixed", // Invalid dot-dash combination
"@tsci/dash-.dot-mixed", // Invalid dash-dot combination
"@tsci/space in name", // Contains space
"@tsci/!", // Invalid character
"@tsci/pkg#123", // Invalid character
"@tsci/@invalid", // Invalid character
]

invalidPackages.forEach((pkg) => {
test(`should not match invalid package: ${pkg}`, () => {
const matches = Array.from(pkg.matchAll(TSCI_PACKAGE_PATTERN))
console.log(Array.from(pkg.matchAll(TSCI_PACKAGE_PATTERN)))
expect(matches).toHaveLength(0)
})
})

// Test import statements
test("should match package names in import statements", () => {
const importStatement =
'import { something } from "@tsci/valid-package" import { other } from "@tsci/other-package.sub"'
const matches = Array.from(importStatement.matchAll(TSCI_PACKAGE_PATTERN))
expect(matches).toHaveLength(2)
expect(matches.map((m) => m[0])).toEqual([
"@tsci/valid-package",
"@tsci/other-package.sub",
])
})
})
12 changes: 12 additions & 0 deletions src/lib/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* Regular expression pattern for matching @tsci package imports
* Rules:
* - Must start with @tsci/
* - First character after @tsci/ must be a letter
* - Can contain letters, numbers, single dashes between alphanumeric characters
* - Can have subpackages separated by single dots
* - Cannot end with dots or dashes
* - Cannot have consecutive dots or dashes
*/
export const TSCI_PACKAGE_PATTERN =
/@tsci\/[a-zA-Z][a-zA-Z0-9]*(?:--?[a-zA-Z0-9]+)*(?:\.[a-zA-Z][a-zA-Z0-9]*(?:--?[a-zA-Z0-9]+)*)*$/g

0 comments on commit 56aeaef

Please sign in to comment.