Skip to content

Commit a80dc86

Browse files
haydenbleaselclaude
andcommitted
fix: resolve lint errors
- use template literals instead of string concatenation - add block statements for early returns - move regex patterns to top-level constants - replace while loop with for...of using matchAll - replace nested ternary with if-else - remove unused variables - fix import ordering and quote styles Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 7cc972c commit a80dc86

6 files changed

Lines changed: 75 additions & 63 deletions

File tree

packages/elements/src/model-selector.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ export const ModelSelectorLogoGroup = ({
194194
}: ModelSelectorLogoGroupProps) => (
195195
<div
196196
className={cn(
197-
"-space-x-1 flex shrink-0 items-center [&>img]:rounded-full [&>img]:bg-background [&>img]:p-px [&>img]:ring-1 dark:[&>img]:bg-foreground",
197+
"flex shrink-0 items-center -space-x-1 [&>img]:rounded-full [&>img]:bg-background [&>img]:p-px [&>img]:ring-1 dark:[&>img]:bg-foreground",
198198
className
199199
)}
200200
{...props}

packages/elements/src/prompt-input.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ import {
3333
SelectTrigger,
3434
SelectValue,
3535
} from "@repo/shadcn-ui/components/ui/select";
36+
import { Spinner } from "@repo/shadcn-ui/components/ui/spinner";
3637
import { cn } from "@repo/shadcn-ui/lib/utils";
3738
import type { ChatStatus, FileUIPart, SourceDocumentUIPart } from "ai";
38-
import { Spinner } from "@repo/shadcn-ui/components/ui/spinner";
3939
import {
4040
CornerDownLeftIcon,
4141
ImageIcon,

packages/elements/src/speech-input.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
"use client";
22

33
import { Button } from "@repo/shadcn-ui/components/ui/button";
4-
import { cn } from "@repo/shadcn-ui/lib/utils";
54
import { Spinner } from "@repo/shadcn-ui/components/ui/spinner";
5+
import { cn } from "@repo/shadcn-ui/lib/utils";
66
import { MicIcon, SquareIcon } from "lucide-react";
77
import {
88
type ComponentProps,

packages/elements/src/voice-selector.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ import {
1919
DialogTitle,
2020
DialogTrigger,
2121
} from "@repo/shadcn-ui/components/ui/dialog";
22-
import { cn } from "@repo/shadcn-ui/lib/utils";
2322
import { Spinner } from "@repo/shadcn-ui/components/ui/spinner";
23+
import { cn } from "@repo/shadcn-ui/lib/utils";
2424
import {
2525
CircleSmallIcon,
2626
MarsIcon,

packages/examples/src/demo-cursor.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ const Example = () => {
422422
let output = "";
423423

424424
for (const line of mockTerminalLines) {
425-
output += line + "\n";
425+
output += `${line}\n`;
426426
setTerminalOutput(output);
427427
await new Promise((resolve) => setTimeout(resolve, 100));
428428
}
@@ -464,7 +464,9 @@ const Example = () => {
464464

465465
// Handle chat submit
466466
const handleSubmit = (message: PromptInputMessage) => {
467-
if (!message.text.trim()) return;
467+
if (!message.text.trim()) {
468+
return;
469+
}
468470

469471
const userMessage: MessageType = {
470472
key: nanoid(),

packages/scripts/src/generate-skills.ts

Lines changed: 67 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
import { existsSync, mkdirSync, rmSync } from 'node:fs';
2-
import { readFile, readdir, writeFile } from 'node:fs/promises';
3-
import { basename, join } from 'node:path';
4-
import matter from 'gray-matter';
5-
6-
const ROOT_DIR = join(import.meta.dirname, '../../..');
7-
const DOCS_DIR = join(ROOT_DIR, 'apps/docs/content/docs');
8-
const COMPONENTS_DIR = join(DOCS_DIR, 'components');
9-
const EXAMPLES_DIR = join(ROOT_DIR, 'packages/examples/src');
10-
const SKILLS_DIR = join(ROOT_DIR, 'skills');
11-
const SKILL_DIR = join(SKILLS_DIR, 'ai-elements');
1+
import { existsSync, mkdirSync, rmSync } from "node:fs";
2+
import { readdir, readFile, writeFile } from "node:fs/promises";
3+
import { basename, join } from "node:path";
4+
import matter from "gray-matter";
5+
6+
const ROOT_DIR = join(import.meta.dirname, "../../..");
7+
const DOCS_DIR = join(ROOT_DIR, "apps/docs/content/docs");
8+
const COMPONENTS_DIR = join(DOCS_DIR, "components");
9+
const EXAMPLES_DIR = join(ROOT_DIR, "packages/examples/src");
10+
const SKILLS_DIR = join(ROOT_DIR, "skills");
11+
const SKILL_DIR = join(SKILLS_DIR, "ai-elements");
1212

1313
const discoverMdxFiles = async (dir: string): Promise<string[]> => {
1414
const results: string[] = [];
@@ -18,7 +18,7 @@ const discoverMdxFiles = async (dir: string): Promise<string[]> => {
1818
const fullPath = join(dir, entry.name);
1919
if (entry.isDirectory()) {
2020
results.push(...(await discoverMdxFiles(fullPath)));
21-
} else if (entry.name.endsWith('.mdx')) {
21+
} else if (entry.name.endsWith(".mdx")) {
2222
results.push(fullPath);
2323
}
2424
}
@@ -35,18 +35,25 @@ const replacePreviews = (content: string): string => {
3535

3636
const removeCustomComponents = (content: string): string => {
3737
return content
38-
.replace(/<ElementsInstaller\s*\/>/g, '')
39-
.replace(/<ElementsDemo\s*\/>/g, '')
40-
.replace(/<Callout>\s*[\s\S]*?<\/Callout>/g, '');
38+
.replace(/<ElementsInstaller\s*\/>/g, "")
39+
.replace(/<ElementsDemo\s*\/>/g, "")
40+
.replace(/<Callout>\s*[\s\S]*?<\/Callout>/g, "");
4141
};
4242

4343
const replaceInstaller = (content: string): string => {
4444
return content.replace(
4545
/<ElementsInstaller\s+path=["']([^"']+)["']\s*\/>/g,
46-
(_, component) => '```bash\nnpx ai-elements@latest add ' + component + '\n```'
46+
(_, component) =>
47+
`\`\`\`bash\nnpx ai-elements@latest add ${component}\n\`\`\``
4748
);
4849
};
4950

51+
const PROP_REGEX = /['"]?([^'":\s]+)['"]?\s*:\s*\{([^}]+)\}/g;
52+
const DESC_REGEX = /description:\s*['"]([^'"]+)['"]/;
53+
const TYPE_REGEX = /type:\s*['"]([^'"]+)['"]/;
54+
const DEFAULT_REGEX = /default:\s*['"]([^'"]+)['"]/;
55+
const REQUIRED_REGEX = /required:\s*true/;
56+
5057
const parseTypeTableProps = (
5158
typeContent: string
5259
): Array<{
@@ -64,22 +71,21 @@ const parseTypeTableProps = (
6471
default?: string;
6572
}> = [];
6673

67-
const propRegex = /['"]?([^'":\s]+)['"]?\s*:\s*\{([^}]+)\}/g;
68-
let match;
74+
const matches = typeContent.matchAll(PROP_REGEX);
6975

70-
while ((match = propRegex.exec(typeContent)) !== null) {
76+
for (const match of matches) {
7177
const propName = match[1];
7278
const propBody = match[2];
7379

74-
const descMatch = propBody.match(/description:\s*['"]([^'"]+)['"]/);
75-
const typeMatch = propBody.match(/type:\s*['"]([^'"]+)['"]/);
76-
const defaultMatch = propBody.match(/default:\s*['"]([^'"]+)['"]/);
77-
const requiredMatch = propBody.match(/required:\s*true/);
80+
const descMatch = propBody.match(DESC_REGEX);
81+
const typeMatch = propBody.match(TYPE_REGEX);
82+
const defaultMatch = propBody.match(DEFAULT_REGEX);
83+
const requiredMatch = propBody.match(REQUIRED_REGEX);
7884

7985
props.push({
8086
name: propName,
81-
type: typeMatch?.[1] || 'unknown',
82-
description: descMatch?.[1] || '',
87+
type: typeMatch?.[1] || "unknown",
88+
description: descMatch?.[1] || "",
8389
required: !!requiredMatch,
8490
default: defaultMatch?.[1],
8591
});
@@ -95,30 +101,31 @@ const replaceTypeTables = (content: string): string => {
95101
const props = parseTypeTableProps(typeContent);
96102

97103
if (props.length === 0) {
98-
return '';
104+
return "";
99105
}
100106

101107
const rows = props.map((prop) => {
102108
const name = `\`${prop.name}\``;
103109
const type = `\`${prop.type}\``;
104-
const defaultVal = prop.required
105-
? 'Required'
106-
: prop.default
107-
? `\`${prop.default}\``
108-
: '-';
110+
let defaultVal = "-";
111+
if (prop.required) {
112+
defaultVal = "Required";
113+
} else if (prop.default) {
114+
defaultVal = `\`${prop.default}\``;
115+
}
109116
return `| ${name} | ${type} | ${defaultVal} | ${prop.description} |`;
110117
});
111118

112119
return [
113-
'| Prop | Type | Default | Description |',
114-
'|------|------|---------|-------------|',
120+
"| Prop | Type | Default | Description |",
121+
"|------|------|---------|-------------|",
115122
...rows,
116-
].join('\n');
123+
].join("\n");
117124
});
118125
};
119126

120127
const removeCallouts = (content: string): string => {
121-
return content.replace(/<Callout[^>]*>[\s\S]*?<\/Callout>/g, '');
128+
return content.replace(/<Callout[^>]*>[\s\S]*?<\/Callout>/g, "");
122129
};
123130

124131
const transformComponentMdx = (fileContent: string): string => {
@@ -147,9 +154,9 @@ const findMatchingExamples = async (
147154
const files = await readdir(EXAMPLES_DIR);
148155

149156
return files.filter((file) => {
150-
const fileBasename = file.replace('.tsx', '');
157+
const fileBasename = file.replace(".tsx", "");
151158
return (
152-
file.endsWith('.tsx') &&
159+
file.endsWith(".tsx") &&
153160
(fileBasename === componentName ||
154161
fileBasename.startsWith(`${componentName}-`))
155162
);
@@ -164,17 +171,13 @@ const cleanSkillsDir = (): void => {
164171
};
165172

166173
const generateOverviewSkill = async (): Promise<void> => {
167-
const indexContent = await readFile(join(DOCS_DIR, 'index.mdx'), 'utf-8');
168-
const usageContent = await readFile(join(DOCS_DIR, 'usage.mdx'), 'utf-8');
174+
const indexContent = await readFile(join(DOCS_DIR, "index.mdx"), "utf-8");
175+
const usageContent = await readFile(join(DOCS_DIR, "usage.mdx"), "utf-8");
169176
const troubleshootingContent = await readFile(
170-
join(DOCS_DIR, 'troubleshooting.mdx'),
171-
'utf-8'
177+
join(DOCS_DIR, "troubleshooting.mdx"),
178+
"utf-8"
172179
);
173180

174-
const indexData = matter(indexContent);
175-
const usageData = matter(usageContent);
176-
const troubleshootingData = matter(troubleshootingContent);
177-
178181
const skillContent = `---
179182
name: ai-elements
180183
description: Create new AI chat interface components for the ai-elements library following established composable patterns, shadcn/ui integration, and Vercel AI SDK conventions. Use when creating new components in packages/elements/src or when the user asks to add a new component to ai-elements.
@@ -198,16 +201,16 @@ See the \`references/\` folder for detailed documentation on each component.
198201
`;
199202

200203
mkdirSync(SKILL_DIR, { recursive: true });
201-
await writeFile(join(SKILL_DIR, 'SKILL.md'), skillContent);
202-
console.log('Generated: SKILL.md (overview)');
204+
await writeFile(join(SKILL_DIR, "SKILL.md"), skillContent);
205+
console.log("Generated: SKILL.md (overview)");
203206
};
204207

205208
const processComponent = async (mdxPath: string): Promise<number> => {
206-
const componentName = basename(mdxPath, '.mdx');
207-
const referencesDir = join(SKILL_DIR, 'references');
208-
const scriptsDir = join(SKILL_DIR, 'scripts');
209+
const componentName = basename(mdxPath, ".mdx");
210+
const referencesDir = join(SKILL_DIR, "references");
211+
const scriptsDir = join(SKILL_DIR, "scripts");
209212

210-
const fileContent = await readFile(mdxPath, 'utf-8');
213+
const fileContent = await readFile(mdxPath, "utf-8");
211214
const { data } = matter(fileContent);
212215

213216
const referenceContent = `# ${data.title}
@@ -225,20 +228,25 @@ ${transformComponentMdx(fileContent)}
225228
if (examples.length > 0) {
226229
mkdirSync(scriptsDir, { recursive: true });
227230
for (const example of examples) {
228-
const exampleContent = await readFile(join(EXAMPLES_DIR, example), 'utf-8');
231+
const exampleContent = await readFile(
232+
join(EXAMPLES_DIR, example),
233+
"utf-8"
234+
);
229235
const transformedContent = exampleContent
230-
.replace(/@repo\/shadcn-ui\//g, '@/')
231-
.replace(/@repo\/elements\//g, '@/components/ai-elements/');
236+
.replace(/@repo\/shadcn-ui\//g, "@/")
237+
.replace(/@repo\/elements\//g, "@/components/ai-elements/");
232238
await writeFile(join(scriptsDir, example), transformedContent);
233239
}
234240
}
235241

236-
console.log(`Generated: references/${componentName}.md (${examples.length} examples)`);
242+
console.log(
243+
`Generated: references/${componentName}.md (${examples.length} examples)`
244+
);
237245
return examples.length;
238246
};
239247

240248
const main = async (): Promise<void> => {
241-
console.log('Generating ai-elements skill from docs and examples...\n');
249+
console.log("Generating ai-elements skill from docs and examples...\n");
242250

243251
cleanSkillsDir();
244252

@@ -252,7 +260,9 @@ const main = async (): Promise<void> => {
252260
totalExamples += await processComponent(mdxPath);
253261
}
254262

255-
console.log(`\nDone! Generated ${mdxFiles.length} references with ${totalExamples} examples.`);
263+
console.log(
264+
`\nDone! Generated ${mdxFiles.length} references with ${totalExamples} examples.`
265+
);
256266
};
257267

258268
main().catch(console.error);

0 commit comments

Comments
 (0)