Skip to content

Commit 8b801c6

Browse files
committed
QoL changes
1 parent 6314b45 commit 8b801c6

File tree

12 files changed

+444
-150
lines changed

12 files changed

+444
-150
lines changed

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ snippetManager.updateConfig({
272272
baseUrl: 'http://your-snippet-server.com/snippets',
273273

274274
// Languages to support
275+
// Note: The first language in this array will be used as the defaultLanguage
275276
supportedLanguages: ['python', 'kotlin', 'typescript'],
276277

277278
// Default imports for each language
@@ -284,3 +285,18 @@ snippetManager.updateConfig({
284285
```
285286

286287
The snippet manager will cache the results, making subsequent fetches instant.
288+
289+
### Default Language Behavior
290+
291+
The `defaultLanguage` in the returned `SnippetResult` is always set to the first language in the `supportedLanguages` array. This means:
292+
293+
1. The order of languages in your `supportedLanguages` configuration determines which language is used as the default
294+
2. This default is set regardless of whether the snippet exists in that language
295+
3. You can control the default language by reordering the `supportedLanguages` array
296+
297+
For example, if you want Kotlin to be the default language, put it first in the array:
298+
```typescript
299+
snippetManager.updateConfig({
300+
supportedLanguages: ['kotlin', 'python', 'typescript'] // Kotlin will be the default
301+
});
302+
```

example/shnippet.config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,6 @@ export const config = {
1010
prependEnd: ":prepend-end:",
1111
},
1212
outputDirectoryStructure: "byLanguage",
13+
baseUrl: "http://localhost:3000",
14+
supportedLanguages: ["python", "kotlin", "javascript"]
1315
};

example/src/App.jsx

Lines changed: 78 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,105 @@
1-
import { useState, useEffect } from "react";
2-
import { snippetManager } from "shnippet";
3-
import { config } from "../shnippet.config";
1+
import { useState, useEffect } from 'react';
2+
import { snippetManager } from 'shnippet';
3+
import { config } from '../shnippet.config';
44

55
// Update the snippetManager with our config
66
snippetManager.updateConfig(config);
77

88
function App() {
9-
const [snippet, setSnippet] = useState("");
10-
const [error, setError] = useState("");
9+
const [snippetResult, setSnippetResult] = useState(null);
10+
const [selectedLanguage, setSelectedLanguage] = useState('');
11+
const [error, setError] = useState('');
1112

1213
useEffect(() => {
1314
async function loadSnippet() {
1415
try {
1516
// Try to load a test snippet
16-
const content = await snippetManager.getSnippet("example1", "python");
17-
setSnippet(content);
17+
const result = await snippetManager.getSnippet('example1');
18+
setSnippetResult(result);
19+
// Set initial language to the default language
20+
setSelectedLanguage(result.defaultLanguage);
1821
} catch (err) {
1922
setError(err.message);
2023
}
2124
}
2225
loadSnippet();
2326
}, []);
2427

28+
if (error) {
29+
return (
30+
<div style={{ padding: '20px' }}>
31+
<h1>Shnippet Test</h1>
32+
<div style={{ color: 'red' }}>Error: {error}</div>
33+
</div>
34+
);
35+
}
36+
37+
if (!snippetResult) {
38+
return (
39+
<div style={{ padding: '20px' }}>
40+
<h1>Shnippet Test</h1>
41+
<div>Loading...</div>
42+
</div>
43+
);
44+
}
45+
2546
return (
26-
<div style={{ padding: "20px" }}>
47+
<div style={{ padding: '20px' }}>
2748
<h1>Shnippet Test</h1>
28-
{error ? (
29-
<div style={{ color: "red" }}>Error: {error}</div>
30-
) : (
49+
50+
{/* Language Tabs */}
51+
<div style={{ marginBottom: '20px' }}>
52+
{snippetResult.languages.map((language) => (
53+
<button
54+
key={language}
55+
onClick={() => setSelectedLanguage(language)}
56+
style={{
57+
padding: '8px 16px',
58+
marginRight: '8px',
59+
border: 'none',
60+
background: selectedLanguage === language ? '#007bff' : '#f0f0f0',
61+
color: selectedLanguage === language ? 'white' : 'black',
62+
cursor: 'pointer',
63+
borderRadius: '4px',
64+
}}
65+
>
66+
{language}
67+
</button>
68+
))}
69+
</div>
70+
71+
{/* Code Display */}
72+
{snippetResult.imports?.[selectedLanguage] && (
73+
<div>
74+
<h3>Imports:</h3>
75+
<pre
76+
style={{
77+
background: '#f5f5f5',
78+
padding: '15px',
79+
borderRadius: '4px',
80+
whiteSpace: 'pre-wrap',
81+
}}
82+
>
83+
{snippetResult.imports[selectedLanguage].join('\n')}
84+
</pre>
85+
</div>
86+
)}
87+
88+
<div style={{ marginBottom: '20px' }}>
89+
<h3>Code:</h3>
3190
<pre
3291
style={{
33-
background: "#f5f5f5",
34-
padding: "15px",
35-
borderRadius: "4px",
36-
whiteSpace: "pre-wrap",
92+
background: '#f5f5f5',
93+
padding: '15px',
94+
borderRadius: '4px',
95+
whiteSpace: 'pre-wrap',
3796
}}
3897
>
39-
{snippet || "Loading..."}
98+
{snippetResult.content[selectedLanguage]}
4099
</pre>
41-
)}
100+
</div>
101+
102+
{/* Imports Display */}
42103
</div>
43104
);
44105
}

package/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "shnippet",
33
"type": "module",
4-
"version": "0.0.1-alpha",
4+
"version": "0.0.2-alpha",
55
"description": "A snippet extraction tool for various programming languages.",
66
"main": "dist/index.js",
77
"browser": "dist/client.browser.js",

package/src/extract/SnippetExtractor.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ export class SnippetExtractor {
2424
private prependBlocks: Record<string, string[]> = {};
2525
private projectRoot: string;
2626
private processedSnippets: Map<string, Set<string>> = new Map();
27+
private languageToDirectory: Record<string, string> = {
28+
python: 'py',
29+
typescript: 'ts',
30+
kotlin: 'kt',
31+
javascript: 'js',
32+
};
2733

2834
constructor(config: SnippetExtractorConfig) {
2935
if (typeof window !== 'undefined') {
@@ -273,17 +279,18 @@ export class SnippetExtractor {
273279

274280
private getLanguageFromExtension(extension: string): string {
275281
const extensionToLanguageMap: Record<string, string> = {
276-
'.js': 'js',
282+
'.js': 'javascript',
277283
'.ts': 'typescript',
278-
'.kt': 'kt',
284+
'.kt': 'kotlin',
285+
'.py': 'python',
279286
'.swift': 'swift',
280287
'.gradle': 'gradle',
281288
'.bash': 'bash',
282289
'.xml': 'xml',
283-
'.py': 'python',
284290
};
285291

286-
return extensionToLanguageMap[extension] || 'other';
292+
const language = extensionToLanguageMap[extension] || 'other';
293+
return this.languageToDirectory[language] || language;
287294
}
288295

289296
public async extractSnippets(): Promise<void> {

package/src/utils/snippetManager.ts

Lines changed: 56 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,16 @@ export interface SnippetConfig {
1616
defaultImports?: Record<string, string[]>;
1717
}
1818

19+
interface SnippetResult {
20+
name: string;
21+
languages: string[];
22+
defaultLanguage: string;
23+
imports?: Record<string, string[]>;
24+
content: Record<string, string>;
25+
}
26+
1927
interface SnippetManager {
20-
getSnippet: (name: string, language: string) => Promise<string>;
21-
getSnippetDisplayInfo: (name: string) => {
22-
languages: string[];
23-
defaultLanguage: string;
24-
imports: Record<string, string[]>;
25-
};
28+
getSnippet: (name: string) => Promise<SnippetResult>;
2629
formatSnippet: (
2730
content: string,
2831
options: { language: string; showLineNumbers?: boolean }
@@ -31,8 +34,14 @@ interface SnippetManager {
3134
}
3235

3336
class SnippetManagerImpl implements SnippetManager {
34-
private cache: Map<string, string> = new Map();
37+
private cache: Map<string, SnippetResult> = new Map();
3538
private config: SnippetConfig;
39+
private languageToDirectory: Record<string, string> = {
40+
python: 'py',
41+
typescript: 'ts',
42+
kotlin: 'kt',
43+
javascript: 'js',
44+
};
3645

3746
constructor(config: Partial<SnippetConfig> = {}) {
3847
this.config = {
@@ -51,36 +60,13 @@ class SnippetManagerImpl implements SnippetManager {
5160
this.cache.clear();
5261
}
5362

54-
async getSnippet(name: string, language: string): Promise<string> {
55-
const key = `${name}-${language}`;
56-
57-
if (this.cache.has(key)) {
58-
return this.cache.get(key)!;
63+
async getSnippet(name: string): Promise<SnippetResult> {
64+
if (this.cache.has(name)) {
65+
return this.cache.get(name)!;
5966
}
6067

61-
try {
62-
const url = `${this.config.baseUrl}/${language}/${name}.snippet.txt`;
63-
console.log('Fetching from:', url);
64-
const response = await fetch(url);
65-
console.log('Response status:', response.status);
66-
console.log('Response type:', response.type);
67-
68-
if (!response.ok) {
69-
throw new Error(`Failed to fetch snippet: ${name} for language: ${language}`);
70-
}
71-
72-
const content = await response.text();
73-
console.log('Received content:', content);
74-
this.cache.set(key, content);
75-
return content;
76-
} catch (error) {
77-
console.error(`Error fetching snippet ${name} for language ${language}:`, error);
78-
throw error;
79-
}
80-
}
81-
82-
getSnippetDisplayInfo(name: string) {
8368
const languages = this.config.supportedLanguages || ['python', 'kotlin'];
69+
const content: Record<string, string> = {};
8470
const imports: Record<string, string[]> = {};
8571

8672
// Use configured imports or defaults
@@ -89,16 +75,43 @@ class SnippetManagerImpl implements SnippetManager {
8975
kotlin: ['import java.util.*'],
9076
};
9177

92-
// Add imports for each supported language
93-
languages.forEach((lang) => {
94-
imports[lang] = defaultImports[lang] || [];
95-
});
78+
try {
79+
// Fetch content for each language
80+
for (const language of languages) {
81+
try {
82+
// Map language names to directory names
83+
const languageDir = this.languageToDirectory[language] || language;
84+
85+
const url = `${this.config.baseUrl}/${languageDir}/${name}.snippet.txt`;
86+
const response = await fetch(url);
87+
88+
if (response.ok) {
89+
content[language] = await response.text();
90+
// Only add imports if they exist for this language
91+
if (defaultImports[language]) {
92+
imports[language] = defaultImports[language];
93+
}
94+
}
95+
} catch (error) {
96+
console.error(`Error fetching ${language} snippet for ${name}:`, error);
97+
}
98+
}
9699

97-
return {
98-
languages,
99-
defaultLanguage: languages[0],
100-
imports,
101-
};
100+
const result: SnippetResult = {
101+
name,
102+
languages: Object.keys(content),
103+
defaultLanguage: languages[0],
104+
content,
105+
// Only include imports if we have any
106+
...(Object.keys(imports).length > 0 && { imports }),
107+
};
108+
109+
this.cache.set(name, result);
110+
return result;
111+
} catch (error) {
112+
console.error(`Error fetching snippet ${name}:`, error);
113+
throw error;
114+
}
102115
}
103116

104117
formatSnippet(content: string, options: { language: string; showLineNumbers?: boolean }): string {
Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
1-
// Example JavaScript file with snippets
2-
//:snippet-start: js-hello
3-
function sayHello() {
4-
console.log('Hello from JavaScript!');
5-
}
6-
//:snippet-end:
1+
// :prepend-start: example1
2+
// JavaScript doesn't need any default imports
3+
// :prepend-end:
74

8-
//:snippet-start: js-class
9-
class Example {
10-
constructor() {
11-
this.message = 'This is a JavaScript class';
12-
}
5+
// :snippet-start: example1
6+
function hello() {
7+
console.log("Hello World!");
8+
console.log("Another print");
9+
}
10+
// :snippet-end:
1311

14-
getMessage() {
15-
return this.message;
16-
}
12+
// :snippet-start: example2
13+
function goodbye() {
14+
console.log("Goodbye World!");
1715
}
18-
//:snippet-end:
16+
// :snippet-end:

package/test/__fixtures__/example.kt

Lines changed: 0 additions & 16 deletions
This file was deleted.

package/test/__fixtures__/example.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
// Example TypeScript file with snippets
2-
//:snippet-start: ts-hello
2+
//:snippet-start: example1
33
function sayHello(): void {
44
console.log('Hello from TypeScript!');
55
}
66
//:snippet-end:
77

8-
//:snippet-start: ts-class
8+
//:snippet-start: example2
99
class Example {
1010
private message: string;
1111
constructor() {

0 commit comments

Comments
 (0)