Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
7c1e6eb
Final sync
NaviAndrei Mar 27, 2026
839cd83
Merge branch 'main' of https://github.com/NaviAndrei/PromptLibrary
NaviAndrei Mar 27, 2026
c9342ae
Merge branch 'main' of https://github.com/NaviAndrei/PromptLibrary
NaviAndrei Mar 27, 2026
dd87efb
build: prepare release v1.1.1 (smart tags, state sync fixes)
NaviAndrei Mar 27, 2026
bc952db
style: fix grid masonry view layout logic
NaviAndrei Mar 27, 2026
84d8fb8
style: increase container width for masonry grid overflow
NaviAndrei Mar 27, 2026
d50292b
style: expand container max-width to 1400px for 3+ column layouts
NaviAndrei Mar 27, 2026
f5d6f79
style: force 3 columns natively using column-count and media queries
NaviAndrei Mar 27, 2026
290f8ae
feat: add global dark mode toggle
NaviAndrei Mar 27, 2026
0812697
Merge remote-tracking branch 'origin/main' into feature/dark-mode
NaviAndrei Mar 27, 2026
223af2a
feat: improve multi-tag autocomplete in PromptForm
NaviAndrei Mar 27, 2026
0d4550c
feat: Smart Workspaces, Variable Injector, Version History with LCS diff
NaviAndrei Mar 27, 2026
c8e63a6
fix: resolve merge conflicts between main and dark mode features
NaviAndrei Mar 27, 2026
b4442a8
chore: translate full project to English (UI, Docs, Comments)
NaviAndrei Mar 27, 2026
0d6928c
fix(workspace): resolve linter error in delete handler and finalize E…
NaviAndrei Mar 27, 2026
5c1099e
Update src/App.tsx
NaviAndrei Mar 27, 2026
a7fa78c
fix: address PR accessibility, key collisions, and async copy issues …
NaviAndrei Mar 27, 2026
75f5812
fix(app): ensure workspace consistency and optimize stats UI (English…
NaviAndrei Mar 27, 2026
46eca91
fix: optimize workspace lookup in list and fix small typo in form
NaviAndrei Mar 27, 2026
bbbe858
fix: memoize diff view, cap LCS lines, fix snapshot timestamp for sta…
NaviAndrei Mar 27, 2026
f9e8f0b
i18n: translate all Romanian UI text and comments to English
NaviAndrei Mar 28, 2026
e89b415
merge: resolve index.css conflict — keep EN translations over RO comm…
NaviAndrei Mar 28, 2026
1ec97d3
chore: release v1.2.5 - Added IndexedDB, PWA Offline Sync, and FlexSe…
NaviAndrei Mar 28, 2026
17ac822
fix(ci): resolve vite-plugin-pwa peer dependency conflict with Vite 8
NaviAndrei Mar 28, 2026
4028c50
fix: production build optimizations and IndexedDB schema refinement
NaviAndrei Mar 28, 2026
f75f457
fix: resolve all type errors and Vite 8 Rolldown build compatibility
NaviAndrei Mar 28, 2026
db0718e
fix(lint): remove unused eslint-disable directive in SearchService.ts
NaviAndrei Mar 28, 2026
e693078
Merge branch 'main' into release/v1.2.5
NaviAndrei Mar 28, 2026
d91a61d
fix: add legacyKey param to useIndexedDB to preserve prompt-history m…
Copilot Mar 28, 2026
82296b6
fix: incremental search index updates and real browser quota in Stora…
Copilot Mar 28, 2026
007e057
fix(hooks): add legacyKey to useEffect dependency array to satisfy ex…
NaviAndrei Mar 28, 2026
e4f4883
fix: improve regex to detect complex variable syntax
NaviAndrei Apr 3, 2026
fcbf9b7
Merge branch 'main' into release/v1.2.5
NaviAndrei Apr 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/components/TemplateManager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ export function TemplateManager({ onSelectTemplate }: TemplateManagerProps) {
return;
}

// Simple regex to extract variables from the template body
const variables = Array.from(form.templateBody.matchAll(/\{\{(\w+)(?::\w+)?(?::[^}]+)?\}\}/g)).map(m => m[1]);
// Permissive regex to extract variables from the template body (supporting {{var}}, {{var=hint}}, {{var:type}})
const variables = Array.from(form.templateBody.matchAll(/\{\{([\w\s-]+)(?:[:=][^}]+)?\}\}/g)).map(m => m[1].trim());

const newTemplate: PromptTemplate = {
id: crypto.randomUUID(),
Expand Down
30 changes: 23 additions & 7 deletions src/components/VariableInjector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,31 @@ const TYPE_MAP: Record<string, string> = {

// Detects all unique variables of type {{name:type:options}} from text
function extractVariables(text: string): (VariableInfo & { options?: string[] })[] {
const regex = /\{\{(\w+)(?::(\w+))?(?::([^}]+))?\}\}/g;
// Permissive regex to support {{var}}, {{var:type}}, {{var:select:a,b}}, and {{var=hint}}
const regex = /\{\{([\w\s-]+)(?:[:=]([^}]+))?\}\}/g;
const seen = new Set<string>();
const variables: (VariableInfo & { options?: string[] })[] = [];

let match;
while ((match = regex.exec(text)) !== null) {
const name = match[1];
const typeHint = (match[2] || 'text').toLowerCase();
const optionsRaw = match[3];
const name = match[1].trim();
const fullHint = (match[2] || '').trim();

if (!seen.has(name)) {
seen.add(name);

// Extract type and options if colon syntax is used
let typeHint = 'text';
let optionsRaw = '';

if (fullHint.includes(':')) {
const parts = fullHint.split(':');
typeHint = parts[0].toLowerCase();
optionsRaw = parts.slice(1).join(':');
} else if (fullHint && !fullHint.includes('=') && TYPE_MAP[fullHint.toLowerCase()]) {
// If it's a recognized type (e.g. {{date:date}}), use it
typeHint = fullHint.toLowerCase();
}
const info: VariableInfo & { options?: string[] } = {
name,
type: TYPE_MAP[typeHint] || 'text',
Expand All @@ -62,10 +75,13 @@ function extractVariables(text: string): (VariableInfo & { options?: string[] })
return variables;
}

// Replaces all occurrences of {{variable}} or {{variable:type}} with the corresponding value
function injectVariables(text: string, values: Record<string, string>): string {
return text.replace(/\{\{(\w+)(?::(\w+))?(?::([^}]+))?\}\}/g, (_, name) => {
return values[name] !== undefined && values[name] !== '' ? values[name] : `{{${name}}}`;
const regex = /\{\{([\w\s-]+)(?:[:=]([^}]+))?\}\}/g;
return text.replace(regex, (fullMatch, name) => {
const trimmedName = name.trim();
return values[trimmedName] !== undefined && values[trimmedName] !== ''
? values[trimmedName]
: fullMatch;
});
}

Expand Down
Loading