@adminide-stack/yantra-help-browser 12.0.16-alpha.19 → 12.0.16-alpha.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,76 @@
1
- import {marked}from'marked';// Configure marked options
1
+ import {marked}from'marked';// Cache for manifest
2
+ let cachedManifest = null;
3
+ let manifestLoadPromise = null;
4
+ // Function to load content manifest
5
+ async function loadContentManifest() {
6
+ if (cachedManifest) {
7
+ return cachedManifest;
8
+ }
9
+ // If already loading, return the existing promise
10
+ if (manifestLoadPromise) {
11
+ return manifestLoadPromise;
12
+ }
13
+ // Check if we're in a browser environment (window.location is only available in browsers)
14
+ const isBrowser = typeof window !== 'undefined' && typeof window.location !== 'undefined';
15
+ if (!isBrowser) {
16
+ // In Node.js/build-time environment, we can't fetch, so return null
17
+ // The sync functions will work with empty data during build
18
+ return null;
19
+ }
20
+ // Create a promise for loading the manifest
21
+ manifestLoadPromise = (async () => {
22
+ try {
23
+ // Try multiple possible paths where the manifest might be served
24
+ const baseUrl = window.location.origin;
25
+ const possiblePaths = [`${baseUrl}/content/content-manifest.json`, '/content/content-manifest.json', './content/content-manifest.json', '../content/content-manifest.json'];
26
+ for (const path of possiblePaths) {
27
+ try {
28
+ const response = await fetch(path);
29
+ if (response.ok) {
30
+ const manifest = await response.json();
31
+ cachedManifest = manifest;
32
+ console.log('✅ Successfully loaded content manifest from:', path);
33
+ return manifest;
34
+ } else {
35
+ console.log(`⚠️ Manifest not found at ${path} (status: ${response.status})`);
36
+ }
37
+ } catch (fetchError) {
38
+ // Try next path
39
+ continue;
40
+ }
41
+ }
42
+ console.error('❌ Could not load content manifest from any path. Tried:', possiblePaths);
43
+ console.error('💡 Make sure content-manifest.json is in the public directory and accessible.');
44
+ return null;
45
+ } catch (error) {
46
+ console.error('❌ Error loading content manifest:', error);
47
+ return null;
48
+ } finally {
49
+ manifestLoadPromise = null;
50
+ }
51
+ })();
52
+ return manifestLoadPromise;
53
+ }
54
+ // Function to get content path map dynamically
55
+ async function getContentPathMap() {
56
+ const manifest = await loadContentManifest();
57
+ if (manifest && manifest.contentPathMap) {
58
+ return manifest.contentPathMap;
59
+ }
60
+ // Fallback to empty map if manifest not available
61
+ return {};
62
+ }
63
+ // Function to get category metadata dynamically
64
+ async function getCategoryMetadata() {
65
+ const manifest = await loadContentManifest();
66
+ if (manifest && manifest.categories) {
67
+ return manifest.categories;
68
+ }
69
+ // Fallback to empty categories if manifest not available
70
+ console.warn('Category metadata not available - manifest may not be loaded');
71
+ return {};
72
+ }
73
+ // Configure marked options
2
74
  marked.setOptions({
3
75
  breaks: true,
4
76
  gfm: true
@@ -16,19 +88,122 @@ const normalizeStaticAssetHref = href => {
16
88
  if (cleaned.startsWith('content/')) return `/${cleaned}`;
17
89
  return href;
18
90
  };
19
- renderer.heading = function (text, level) {
91
+ renderer.heading = function ({
92
+ tokens,
93
+ depth
94
+ }) {
95
+ // Extract text from tokens for ID generation
96
+ const extractText = tokenArray => {
97
+ return tokenArray.map(token => {
98
+ if (token.type === 'text') {
99
+ return token.raw || token.text || '';
100
+ }
101
+ if (token.tokens) {
102
+ return extractText(token.tokens);
103
+ }
104
+ return token.raw || '';
105
+ }).join('');
106
+ };
107
+ // Render tokens to HTML
108
+ const renderInline = tokenArray => {
109
+ return tokenArray.map(token => {
110
+ if (token.type === 'text') {
111
+ // Escape HTML for text tokens
112
+ const text = token.raw || token.text || '';
113
+ return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
114
+ }
115
+ // Handle other inline token types
116
+ if (token.type === 'strong' && token.tokens) {
117
+ return `<strong>${renderInline(token.tokens)}</strong>`;
118
+ }
119
+ if (token.type === 'em' && token.tokens) {
120
+ return `<em>${renderInline(token.tokens)}</em>`;
121
+ }
122
+ if (token.type === 'code') {
123
+ const code = token.raw || token.text || '';
124
+ return `<code>${code.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')}</code>`;
125
+ }
126
+ if (token.tokens) {
127
+ return renderInline(token.tokens);
128
+ }
129
+ return token.raw || '';
130
+ }).join('');
131
+ };
132
+ const text = extractText(tokens);
133
+ const renderedText = renderInline(tokens);
20
134
  const id = text.toLowerCase().replace(/[^\w\s-]/g, '') // Remove special characters
21
135
  .replace(/\s+/g, '-') // Replace spaces with hyphens
22
136
  .replace(/-+/g, '-') // Replace multiple hyphens with single hyphen
23
137
  .trim();
24
- return `<h${level} id="${id}">${text}</h${level}>`;
138
+ return `<h${depth} id="${id}">${renderedText}</h${depth}>`;
25
139
  };
26
- renderer.image = function (href, title, text) {
140
+ renderer.image = function ({
141
+ href,
142
+ title,
143
+ text
144
+ }) {
27
145
  const src = href ? normalizeStaticAssetHref(href) : '';
28
146
  const safeAlt = (text || '').replaceAll('"', '&quot;');
29
147
  const titleAttr = title ? ` title="${title.replaceAll('"', '&quot;')}"` : '';
30
148
  return `<img src="${src}" alt="${safeAlt}"${titleAttr} />`;
31
149
  };
150
+ // Code block renderer with copy button
151
+ renderer.code = function ({
152
+ text,
153
+ lang
154
+ }) {
155
+ // Escape HTML in code content
156
+ const escapeHtml = str => {
157
+ return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;');
158
+ };
159
+ const escapedCode = escapeHtml(text);
160
+ const language = lang || 'plaintext';
161
+ `copy-btn-${Math.random().toString(36).substring(2, 11)}`;
162
+ const codeBlockId = `code-block-${Math.random().toString(36).substring(2, 11)}`;
163
+ return `
164
+ <div class="code-block-wrapper bg-background text-primary" style="position: relative; margin: 1em 0;">
165
+ <button
166
+ class="copy-code-btn"
167
+ data-code-id="${codeBlockId}"
168
+ style="
169
+ position: absolute;
170
+ top: 0.5em;
171
+ right: 0.5em;
172
+ padding: 0.25em 0.75em;
173
+ border: 1px solid #d1d5db;
174
+ border-radius: 8px;
175
+ cursor: pointer;
176
+ font-size: 0.875em;
177
+ z-index: 10;
178
+ transition: all 0.2s;
179
+ "
180
+ onmouseover="this.style.background='#e5e7eb'"
181
+ onmouseout="this.style.background='#f3f4f6'"
182
+ onclick="
183
+ const codeEl = document.getElementById('${codeBlockId}');
184
+ if (codeEl) {
185
+ const text = codeEl.textContent || codeEl.innerText || '';
186
+ navigator.clipboard.writeText(text).then(() => {
187
+ const btn = event.target;
188
+ const originalText = btn.textContent;
189
+ btn.textContent = 'Copied!';
190
+ setTimeout(() => {
191
+ btn.textContent = originalText;
192
+ }, 2000);
193
+ }).catch(() => {
194
+ alert('Failed to copy code');
195
+ });
196
+ }
197
+ "
198
+ >
199
+ Copy
200
+ </button>
201
+ <pre class="bg-background text-primary border border-border rounded-lg overflow-x-auto" style="margin: 0; padding: 1em; overflow-x: auto;">
202
+ <code id="${codeBlockId}" class="language-${language}" style="display: block; font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace; font-size: 0.875em; line-height: 1.5;">${escapedCode}</code>
203
+ </pre>
204
+ </div>
205
+ `;
206
+ };
32
207
  marked.setOptions({
33
208
  renderer: renderer
34
209
  });
@@ -55,84 +230,8 @@ const extractHeadings = markdownContent => {
55
230
  // Function to load markdown content dynamically
56
231
  const loadMarkdownContent = async contentId => {
57
232
  try {
58
- // Map content IDs to file paths based on actual content structure
59
- const contentPathMap = {
60
- 'what-is-yantra-intro': '/content/what-is-yantra/what-is-yantra-intro.md',
61
- 'how-yantra-works': '/content/what-is-yantra/how-yantra-works.md',
62
- 'practical-tips-yantra': '/content/what-is-yantra/practical-tips-yantra.md',
63
- 'yantra-discord-community': '/content/what-is-yantra/yantra-discord-community.md',
64
- 'getting-started-yantra': '/content/what-is-yantra/getting-started-yantra.md',
65
- 'yantra-pro-overview': '/content/yantra-pro-max/yantra-pro-overview.md',
66
- 'yantra-max-features': '/content/yantra-pro-max/yantra-max-features.md',
67
- 'pro-pricing': '/content/yantra-pro-max/pro-pricing.md',
68
- 'subscription-benefits': '/content/yantra-pro-max/subscription-benefits.md',
69
- 'upgrade-process': '/content/yantra-pro-max/upgrade-process.md',
70
- 'billing-management': '/content/yantra-pro-max/billing-management.md',
71
- 'cancellation-refund': '/content/yantra-pro-max/cancellation-refund.md',
72
- 'search-features': '/content/product-features/search-features.md',
73
- 'ai-models': '/content/product-features/ai-models.md',
74
- 'conversation-features': '/content/product-features/conversation-features.md',
75
- 'source-citations': '/content/product-features/source-citations.md',
76
- 'real-time-search': '/content/product-features/real-time-search.md',
77
- 'follow-up-questions': '/content/product-features/follow-up-questions.md',
78
- 'search-history': '/content/product-features/search-history.md',
79
- 'saved-searches': '/content/product-features/saved-searches.md',
80
- 'export-features': '/content/product-features/export-features.md',
81
- 'collaboration-tools': '/content/product-features/collaboration-tools.md',
82
- 'billing-overview': '/content/subscription-billing/billing-overview.md',
83
- 'payment-methods': '/content/subscription-billing/payment-methods.md',
84
- 'billing-cycle': '/content/subscription-billing/billing-cycle.md',
85
- 'promotional-offers': '/content/subscription-billing/promotional-offers.md',
86
- 'student-discounts': '/content/subscription-billing/student-discounts.md',
87
- 'enterprise-pricing': '/content/subscription-billing/enterprise-pricing.md',
88
- 'invoice-management': '/content/subscription-billing/invoice-management.md',
89
- 'tax-information': '/content/subscription-billing/tax-information.md',
90
- 'billing-support': '/content/subscription-billing/billing-support.md',
91
- 'refund-policy': '/content/subscription-billing/refund-policy.md',
92
- 'currency-support': '/content/subscription-billing/currency-support.md',
93
- 'regular-search': '/content/search-modes/regular-search.md',
94
- 'pro-search': '/content/search-modes/pro-search.md',
95
- 'deep-research': '/content/search-modes/deep-research.md',
96
- 'labs-features': '/content/search-modes/labs-features.md',
97
- 'profile-settings': '/content/account-management/profile-settings.md',
98
- 'account-setup': '/content/account-management/account-setup.md',
99
- preferences: '/content/account-management/preferences.md',
100
- 'privacy-settings': '/content/account-management/privacy-settings.md',
101
- 'delete-account': '/content/account-management/delete-account.md',
102
- 'mobile-app-overview': '/content/yantra-assistant/mobile-app-overview.md',
103
- 'ios-app': '/content/yantra-assistant/ios-app.md',
104
- 'android-app': '/content/yantra-assistant/android-app.md',
105
- 'voice-assistant': '/content/yantra-assistant/voice-assistant.md',
106
- 'privacy-policy': '/content/data-privacy/privacy-policy.md',
107
- 'data-collection': '/content/data-privacy/data-collection.md',
108
- 'spaces-overview': '/content/spaces-library/spaces-overview.md',
109
- 'threads-overview': '/content/threads/threads-overview.md',
110
- 'conversation-management': '/content/threads/conversation-management.md',
111
- 'api-overview': '/content/scope-api/api-overview.md',
112
- 'file-upload-overview': '/content/file-uploads/file-upload-overview.md',
113
- 'getting-started-guide': '/content/getting-started/getting-started-guide.md',
114
- 'student-overview': '/content/student-hub/student-overview.md',
115
- 'student-discounts-hub': '/content/student-hub/student-discounts.md',
116
- 'academic-research': '/content/student-hub/academic-research.md',
117
- 'study-tools': '/content/student-hub/study-tools.md',
118
- 'privacy-requests': '/content/data-subject-privacy/privacy-requests.md',
119
- 'data-access': '/content/data-subject-privacy/data-access.md',
120
- 'data-portability': '/content/data-subject-privacy/data-portability.md',
121
- 'technical-overview': '/content/technical-questions/technical-overview.md',
122
- 'ai-models-technical': '/content/technical-questions/ai-models-technical.md',
123
- 'search-algorithms': '/content/technical-questions/search-algorithms.md',
124
- 'data-processing': '/content/technical-questions/data-processing.md',
125
- infrastructure: '/content/technical-questions/infrastructure.md',
126
- 'performance-optimization': '/content/technical-questions/performance-optimization.md',
127
- 'api-technical': '/content/technical-questions/api-technical.md',
128
- 'database-architecture': '/content/technical-questions/database-architecture.md',
129
- 'enterprise-overview': '/content/yantra-enterprise/enterprise-overview.md',
130
- 'admin-dashboard': '/content/yantra-enterprise/admin-dashboard.md',
131
- 'user-management': '/content/yantra-enterprise/user-management.md',
132
- 'sso-integration': '/content/yantra-enterprise/sso-integration.md',
133
- 'custom-branding': '/content/yantra-enterprise/custom-branding.md',
134
- 'dedicated-support': '/content/yantra-enterprise/dedicated-support.md'
135
- };
233
+ // Get content path map dynamically from manifest
234
+ const contentPathMap = await getContentPathMap();
136
235
  const filePath = contentPathMap[contentId];
137
236
  if (!filePath) {
138
237
  console.warn(`No markdown file found for content ID: ${contentId}`);
@@ -203,769 +302,85 @@ For advanced users, here are some additional tips and techniques:
203
302
 
204
303
  If you need help with this topic, please refer to our support resources or contact our team.`;
205
304
  };
206
- // Category metadata - this defines the structure and metadata based on actual content
207
- const categoryMetadata = {
208
- 'what-is-yantra': {
209
- id: 'what-is-yantra',
210
- title: 'What is Yantra?',
211
- description: 'Introduction | Overview | Getting Started',
212
- iconType: 'Perplexity',
213
- articles: [{
214
- id: 'what-is-yantra-intro',
215
- title: 'What is Yantra?',
216
- description: 'Learn more about Yantra and what sets us apart from traditional search engines.',
217
- slug: 'what-is-yantra-intro',
218
- author: 'Beena',
219
- updatedAt: '4 months ago',
220
- categoryId: 'what-is-yantra'
221
- }, {
222
- id: 'how-yantra-works',
223
- title: 'How does Yantra work?',
224
- description: 'Learn how Yantra uses AI to search the web and provide conversational answers.',
225
- slug: 'how-yantra-works',
226
- author: 'Beena',
227
- updatedAt: '4 months ago',
228
- categoryId: 'what-is-yantra'
229
- }, {
230
- id: 'practical-tips-yantra',
231
- title: 'Practical Tips for Using Yantra',
232
- description: 'Maximize your productivity with these practical tips for using Yantra effectively.',
233
- slug: 'practical-tips-yantra',
234
- author: 'Beena',
235
- updatedAt: '4 months ago',
236
- categoryId: 'what-is-yantra'
237
- }, {
238
- id: 'yantra-discord-community',
239
- title: 'Yantra Discord Community',
240
- description: 'Join our vibrant Discord community to connect with other Yantra users, get help, and share insights.',
241
- slug: 'yantra-discord-community',
242
- author: 'Beena',
243
- updatedAt: '4 months ago',
244
- categoryId: 'what-is-yantra'
245
- }, {
246
- id: 'getting-started-yantra',
247
- title: 'Getting Started with Yantra',
248
- description: 'A comprehensive guide to help you get started with Yantra and make the most of its features.',
249
- slug: 'getting-started-yantra',
250
- author: 'Beena',
251
- updatedAt: '4 months ago',
252
- categoryId: 'what-is-yantra'
253
- }]
254
- },
255
- 'yantra-pro-max': {
256
- id: 'yantra-pro-max',
257
- title: 'Yantra Pro and Max',
258
- description: 'Pro | Max | Pricing | Billing',
259
- iconType: 'Pro',
260
- articles: [{
261
- id: 'yantra-pro-overview',
262
- title: 'Yantra Pro Overview',
263
- description: 'Learn about Yantra Pro features and benefits.',
264
- slug: 'yantra-pro-overview',
265
- author: 'Beena',
266
- updatedAt: '4 months ago',
267
- categoryId: 'yantra-pro-max'
268
- }, {
269
- id: 'yantra-max-features',
270
- title: 'Yantra Max Features',
271
- description: 'Discover the advanced features available in Yantra Max.',
272
- slug: 'yantra-max-features',
273
- author: 'Beena',
274
- updatedAt: '4 months ago',
275
- categoryId: 'yantra-pro-max'
276
- }, {
277
- id: 'pro-pricing',
278
- title: 'Pro Pricing',
279
- description: 'Understand Yantra Pro pricing and what you get with your subscription.',
280
- slug: 'pro-pricing',
281
- author: 'Beena',
282
- updatedAt: '4 months ago',
283
- categoryId: 'yantra-pro-max'
284
- }, {
285
- id: 'subscription-benefits',
286
- title: 'Subscription Benefits',
287
- description: 'Explore the benefits of subscribing to Yantra Pro or Max.',
288
- slug: 'subscription-benefits',
289
- author: 'Beena',
290
- updatedAt: '4 months ago',
291
- categoryId: 'yantra-pro-max'
292
- }, {
293
- id: 'upgrade-process',
294
- title: 'Upgrade Process',
295
- description: 'Learn how to upgrade your Yantra account to Pro or Max.',
296
- slug: 'upgrade-process',
297
- author: 'Beena',
298
- updatedAt: '4 months ago',
299
- categoryId: 'yantra-pro-max'
300
- }, {
301
- id: 'billing-management',
302
- title: 'Billing Management',
303
- description: 'Manage your Yantra subscription billing and payment methods.',
304
- slug: 'billing-management',
305
- author: 'Beena',
306
- updatedAt: '4 months ago',
307
- categoryId: 'yantra-pro-max'
308
- }, {
309
- id: 'cancellation-refund',
310
- title: 'Cancellation & Refund',
311
- description: 'Information about canceling your subscription and refund policies.',
312
- slug: 'cancellation-refund',
313
- author: 'Beena',
314
- updatedAt: '4 months ago',
315
- categoryId: 'yantra-pro-max'
316
- }]
317
- },
318
- 'product-features': {
319
- id: 'product-features',
320
- title: 'Product Features',
321
- description: 'Search | AI | Citations | Export',
322
- iconType: 'Features',
323
- articles: [{
324
- id: 'search-features',
325
- title: 'Search Features',
326
- description: "Explore Yantra's powerful search capabilities and features.",
327
- slug: 'search-features',
328
- author: 'Beena',
329
- updatedAt: '4 months ago',
330
- categoryId: 'product-features'
331
- }, {
332
- id: 'ai-models',
333
- title: 'AI Models',
334
- description: "Learn about the AI models powering Yantra's search and answers.",
335
- slug: 'ai-models',
336
- author: 'Beena',
337
- updatedAt: '4 months ago',
338
- categoryId: 'product-features'
339
- }, {
340
- id: 'conversation-features',
341
- title: 'Conversation Features',
342
- description: "Discover Yantra's conversational AI capabilities.",
343
- slug: 'conversation-features',
344
- author: 'Beena',
345
- updatedAt: '4 months ago',
346
- categoryId: 'product-features'
347
- }, {
348
- id: 'source-citations',
349
- title: 'Source Citations',
350
- description: 'Understand how Yantra provides verifiable source citations.',
351
- slug: 'source-citations',
352
- author: 'Beena',
353
- updatedAt: '4 months ago',
354
- categoryId: 'product-features'
355
- }, {
356
- id: 'real-time-search',
357
- title: 'Real-time Search',
358
- description: "Learn about Yantra's real-time web search capabilities.",
359
- slug: 'real-time-search',
360
- author: 'Beena',
361
- updatedAt: '4 months ago',
362
- categoryId: 'product-features'
363
- }, {
364
- id: 'follow-up-questions',
365
- title: 'Follow-up Questions',
366
- description: 'Master the art of asking effective follow-up questions.',
367
- slug: 'follow-up-questions',
368
- author: 'Beena',
369
- updatedAt: '4 months ago',
370
- categoryId: 'product-features'
371
- }, {
372
- id: 'search-history',
373
- title: 'Search History',
374
- description: 'Access and manage your Yantra search history.',
375
- slug: 'search-history',
376
- author: 'Beena',
377
- updatedAt: '4 months ago',
378
- categoryId: 'product-features'
379
- }, {
380
- id: 'saved-searches',
381
- title: 'Saved Searches',
382
- description: 'Save and organize your frequently used searches.',
383
- slug: 'saved-searches',
384
- author: 'Beena',
385
- updatedAt: '4 months ago',
386
- categoryId: 'product-features'
387
- }, {
388
- id: 'export-features',
389
- title: 'Export Features',
390
- description: 'Export your Yantra research and answers in various formats.',
391
- slug: 'export-features',
392
- author: 'Beena',
393
- updatedAt: '4 months ago',
394
- categoryId: 'product-features'
395
- }, {
396
- id: 'collaboration-tools',
397
- title: 'Collaboration Tools',
398
- description: "Collaborate with others using Yantra's sharing and team features.",
399
- slug: 'collaboration-tools',
400
- author: 'Beena',
401
- updatedAt: '4 months ago',
402
- categoryId: 'product-features'
403
- }]
404
- },
405
- 'subscription-billing': {
406
- id: 'subscription-billing',
407
- title: 'Subscription, Billing & Promotions',
408
- description: 'Billing | Payment | Promotions | Refunds',
409
- iconType: 'Subscription',
410
- articles: [{
411
- id: 'billing-overview',
412
- title: 'Billing Overview',
413
- description: "Understand Yantra's billing system and subscription options.",
414
- slug: 'billing-overview',
415
- author: 'Beena',
416
- updatedAt: '4 months ago',
417
- categoryId: 'subscription-billing'
418
- }, {
419
- id: 'payment-methods',
420
- title: 'Payment Methods',
421
- description: 'Learn about accepted payment methods and how to update them.',
422
- slug: 'payment-methods',
423
- author: 'Beena',
424
- updatedAt: '4 months ago',
425
- categoryId: 'subscription-billing'
426
- }, {
427
- id: 'billing-cycle',
428
- title: 'Billing Cycle',
429
- description: 'Understand your billing cycle and when charges occur.',
430
- slug: 'billing-cycle',
431
- author: 'Beena',
432
- updatedAt: '4 months ago',
433
- categoryId: 'subscription-billing'
434
- }, {
435
- id: 'promotional-offers',
436
- title: 'Promotional Offers',
437
- description: 'Learn about current promotional offers and discounts.',
438
- slug: 'promotional-offers',
439
- author: 'Beena',
440
- updatedAt: '4 months ago',
441
- categoryId: 'subscription-billing'
442
- }, {
443
- id: 'student-discounts',
444
- title: 'Student Discounts',
445
- description: 'Information about student discounts and verification.',
446
- slug: 'student-discounts',
447
- author: 'Beena',
448
- updatedAt: '4 months ago',
449
- categoryId: 'subscription-billing'
450
- }, {
451
- id: 'enterprise-pricing',
452
- title: 'Enterprise Pricing',
453
- description: 'Learn about enterprise pricing and custom solutions.',
454
- slug: 'enterprise-pricing',
455
- author: 'Beena',
456
- updatedAt: '4 months ago',
457
- categoryId: 'subscription-billing'
458
- }, {
459
- id: 'invoice-management',
460
- title: 'Invoice Management',
461
- description: 'Access and manage your Yantra invoices and billing history.',
462
- slug: 'invoice-management',
463
- author: 'Beena',
464
- updatedAt: '4 months ago',
465
- categoryId: 'subscription-billing'
466
- }, {
467
- id: 'tax-information',
468
- title: 'Tax Information',
469
- description: 'Information about taxes and tax reporting for Yantra subscriptions.',
470
- slug: 'tax-information',
471
- author: 'Beena',
472
- updatedAt: '4 months ago',
473
- categoryId: 'subscription-billing'
474
- }, {
475
- id: 'billing-support',
476
- title: 'Billing Support',
477
- description: 'Get help with billing questions and issues.',
478
- slug: 'billing-support',
479
- author: 'Beena',
480
- updatedAt: '4 months ago',
481
- categoryId: 'subscription-billing'
482
- }, {
483
- id: 'refund-policy',
484
- title: 'Refund Policy',
485
- description: "Understand Yantra's refund policy and how to request refunds.",
486
- slug: 'refund-policy',
487
- author: 'Beena',
488
- updatedAt: '4 months ago',
489
- categoryId: 'subscription-billing'
490
- }, {
491
- id: 'currency-support',
492
- title: 'Currency Support',
493
- description: 'Learn about supported currencies and international billing.',
494
- slug: 'currency-support',
495
- author: 'Beena',
496
- updatedAt: '4 months ago',
497
- categoryId: 'subscription-billing'
498
- }]
499
- },
500
- 'search-modes': {
501
- id: 'search-modes',
502
- title: 'Search Modes',
503
- description: 'Regular | Pro | Deep Research | Labs',
504
- iconType: 'SearchModes',
505
- articles: [{
506
- id: 'regular-search',
507
- title: 'Regular Search',
508
- description: "Learn about Yantra's regular search mode and its capabilities.",
509
- slug: 'regular-search',
510
- author: 'Beena',
511
- updatedAt: '4 months ago',
512
- categoryId: 'search-modes'
513
- }, {
514
- id: 'pro-search',
515
- title: 'Pro Search',
516
- description: 'Discover the enhanced features available in Pro search mode.',
517
- slug: 'pro-search',
518
- author: 'Beena',
519
- updatedAt: '4 months ago',
520
- categoryId: 'search-modes'
521
- }, {
522
- id: 'deep-research',
523
- title: 'Deep Research',
524
- description: "Master Yantra's deep research mode for comprehensive analysis.",
525
- slug: 'deep-research',
526
- author: 'Beena',
527
- updatedAt: '4 months ago',
528
- categoryId: 'search-modes'
529
- }, {
530
- id: 'labs-features',
531
- title: 'Labs Features',
532
- description: 'Explore experimental features and capabilities in Yantra Labs.',
533
- slug: 'labs-features',
534
- author: 'Beena',
535
- updatedAt: '4 months ago',
536
- categoryId: 'search-modes'
537
- }]
538
- },
539
- 'yantra-enterprise': {
540
- id: 'yantra-enterprise',
541
- title: 'Yantra Enterprise',
542
- description: 'Enterprise | Admin | SSO | Branding',
543
- iconType: 'Enterprise',
544
- articles: [{
545
- id: 'enterprise-overview',
546
- title: 'Enterprise Overview',
547
- description: 'Introduction to Yantra Enterprise features and benefits.',
548
- slug: 'enterprise-overview',
549
- author: 'Beena',
550
- updatedAt: '4 months ago',
551
- categoryId: 'yantra-enterprise'
552
- }, {
553
- id: 'admin-dashboard',
554
- title: 'Admin Dashboard',
555
- description: "Managing your organization's Yantra deployment.",
556
- slug: 'admin-dashboard',
557
- author: 'Beena',
558
- updatedAt: '4 months ago',
559
- categoryId: 'yantra-enterprise'
560
- }, {
561
- id: 'user-management',
562
- title: 'User Management',
563
- description: 'Adding, removing, and managing enterprise users.',
564
- slug: 'user-management',
565
- author: 'Beena',
566
- updatedAt: '4 months ago',
567
- categoryId: 'yantra-enterprise'
568
- }, {
569
- id: 'sso-integration',
570
- title: 'SSO Integration',
571
- description: 'Single Sign-On integration for enterprise customers.',
572
- slug: 'sso-integration',
573
- author: 'Beena',
574
- updatedAt: '4 months ago',
575
- categoryId: 'yantra-enterprise'
576
- }, {
577
- id: 'custom-branding',
578
- title: 'Custom Branding',
579
- description: 'White-label solutions and custom branding options.',
580
- slug: 'custom-branding',
581
- author: 'Beena',
582
- updatedAt: '4 months ago',
583
- categoryId: 'yantra-enterprise'
584
- }, {
585
- id: 'dedicated-support',
586
- title: 'Dedicated Support',
587
- description: 'Priority support and dedicated account management.',
588
- slug: 'dedicated-support',
589
- author: 'Beena',
590
- updatedAt: '4 months ago',
591
- categoryId: 'yantra-enterprise'
592
- }]
593
- },
594
- 'account-management': {
595
- id: 'account-management',
596
- title: 'Account Management & Settings',
597
- description: 'Profile | Settings | Privacy | Account',
598
- iconType: 'Account',
599
- articles: [{
600
- id: 'profile-settings',
601
- title: 'Profile Settings',
602
- description: 'Manage your Yantra profile and personal information.',
603
- slug: 'profile-settings',
604
- author: 'Beena',
605
- updatedAt: '4 months ago',
606
- categoryId: 'account-management'
607
- }, {
608
- id: 'account-setup',
609
- title: 'Account Setup',
610
- description: 'Complete guide to setting up your Yantra account.',
611
- slug: 'account-setup',
612
- author: 'Beena',
613
- updatedAt: '4 months ago',
614
- categoryId: 'account-management'
615
- }, {
616
- id: 'preferences',
617
- title: 'Preferences',
618
- description: 'Customize your Yantra experience with personal preferences.',
619
- slug: 'preferences',
620
- author: 'Beena',
621
- updatedAt: '4 months ago',
622
- categoryId: 'account-management'
623
- }, {
624
- id: 'privacy-settings',
625
- title: 'Privacy Settings',
626
- description: 'Control your privacy and data sharing preferences.',
627
- slug: 'privacy-settings',
628
- author: 'Beena',
629
- updatedAt: '4 months ago',
630
- categoryId: 'account-management'
631
- }, {
632
- id: 'delete-account',
633
- title: 'Delete Account',
634
- description: 'Learn how to delete your Yantra account and what happens to your data.',
635
- slug: 'delete-account',
636
- author: 'Beena',
637
- updatedAt: '4 months ago',
638
- categoryId: 'account-management'
639
- }]
640
- },
641
- 'yantra-assistant': {
642
- id: 'yantra-assistant',
643
- title: 'Yantra Assistant',
644
- description: 'Mobile | iOS | Android | Voice',
645
- iconType: 'Assistant',
646
- articles: [{
647
- id: 'mobile-app-overview',
648
- title: 'Mobile App Overview',
649
- description: "Overview of Yantra's mobile applications and features.",
650
- slug: 'mobile-app-overview',
651
- author: 'Beena',
652
- updatedAt: '4 months ago',
653
- categoryId: 'yantra-assistant'
654
- }, {
655
- id: 'ios-app',
656
- title: 'iOS App',
657
- description: "Learn about Yantra's iOS app features and capabilities.",
658
- slug: 'ios-app',
659
- author: 'Beena',
660
- updatedAt: '4 months ago',
661
- categoryId: 'yantra-assistant'
662
- }, {
663
- id: 'android-app',
664
- title: 'Android App',
665
- description: "Discover Yantra's Android app features and functionality.",
666
- slug: 'android-app',
667
- author: 'Beena',
668
- updatedAt: '4 months ago',
669
- categoryId: 'yantra-assistant'
670
- }, {
671
- id: 'voice-assistant',
672
- title: 'Voice Assistant',
673
- description: "Use Yantra's voice assistant for hands-free searching.",
674
- slug: 'voice-assistant',
675
- author: 'Beena',
676
- updatedAt: '4 months ago',
677
- categoryId: 'yantra-assistant'
678
- }]
679
- },
680
- 'data-privacy': {
681
- id: 'data-privacy',
682
- title: 'Data Privacy & Security',
683
- description: 'Privacy | Security | Data | Compliance',
684
- iconType: 'Privacy',
685
- articles: [{
686
- id: 'privacy-policy',
687
- title: 'Privacy Policy',
688
- description: 'Understand how Yantra protects your privacy and handles your data.',
689
- slug: 'privacy-policy',
690
- author: 'Beena',
691
- updatedAt: '4 months ago',
692
- categoryId: 'data-privacy'
693
- }, {
694
- id: 'data-collection',
695
- title: 'Data Collection',
696
- description: "Learn about what data Yantra collects and how it's used.",
697
- slug: 'data-collection',
698
- author: 'Beena',
699
- updatedAt: '4 months ago',
700
- categoryId: 'data-privacy'
701
- }]
702
- },
703
- 'spaces-library': {
704
- id: 'spaces-library',
705
- title: 'Spaces & Library',
706
- description: 'Spaces | Library | Collections | Organization',
707
- iconType: 'Spaces',
708
- articles: [{
709
- id: 'spaces-overview',
710
- title: 'Spaces Overview',
711
- description: 'Learn about Yantra Spaces and how to organize your research.',
712
- slug: 'spaces-overview',
713
- author: 'Beena',
714
- updatedAt: '4 months ago',
715
- categoryId: 'spaces-library'
716
- }]
717
- },
718
- threads: {
719
- id: 'threads',
720
- title: 'Threads',
721
- description: 'Threads | Conversations | History | Management',
722
- iconType: 'Threads',
723
- articles: [{
724
- id: 'threads-overview',
725
- title: 'Threads Overview',
726
- description: 'Understand Yantra threads and conversation management.',
727
- slug: 'threads-overview',
728
- author: 'Beena',
729
- updatedAt: '4 months ago',
730
- categoryId: 'threads'
731
- }, {
732
- id: 'conversation-management',
733
- title: 'Conversation Management',
734
- description: 'Learn how to manage your Yantra conversations and threads.',
735
- slug: 'conversation-management',
736
- author: 'Beena',
737
- updatedAt: '4 months ago',
738
- categoryId: 'threads'
739
- }]
740
- },
741
- troubleshooting: {
742
- id: 'troubleshooting',
743
- title: 'Troubleshooting & Support',
744
- description: 'Troubleshooting | Support | FAQ | Help',
745
- iconType: 'Troubleshooting',
746
- articles: [{
747
- id: 'general-support',
748
- title: 'General Support',
749
- description: 'Get help with common issues and find support resources.',
750
- slug: 'general-support',
751
- author: 'Beena',
752
- updatedAt: '4 months ago',
753
- categoryId: 'troubleshooting'
754
- }]
755
- },
756
- 'scope-api': {
757
- id: 'scope-api',
758
- title: 'Scope & Open Source API',
759
- description: 'API | Open Source | Integration | Development',
760
- iconType: 'Api',
761
- articles: [{
762
- id: 'api-overview',
763
- title: 'API Overview',
764
- description: "Learn about Yantra's API and integration capabilities.",
765
- slug: 'api-overview',
766
- author: 'Beena',
767
- updatedAt: '4 months ago',
768
- categoryId: 'scope-api'
769
- }]
770
- },
771
- 'file-uploads': {
772
- id: 'file-uploads',
773
- title: 'File Uploads & File API',
774
- description: 'File Upload | File API | Documents | Processing',
775
- iconType: 'FileUploads',
776
- articles: [{
777
- id: 'file-upload-overview',
778
- title: 'File Upload Overview',
779
- description: 'Learn how to upload and process files with Yantra.',
780
- slug: 'file-upload-overview',
781
- author: 'Beena',
782
- updatedAt: '4 months ago',
783
- categoryId: 'file-uploads'
784
- }]
785
- },
786
- 'getting-started': {
787
- id: 'getting-started',
788
- title: 'Getting Started',
789
- description: 'Getting Started | Setup | First Steps | Guide',
790
- iconType: 'GettingStarted',
791
- articles: [{
792
- id: 'getting-started-guide',
793
- title: 'Getting Started Guide',
794
- description: 'Complete guide to getting started with Yantra.',
795
- slug: 'getting-started-guide',
796
- author: 'Beena',
797
- updatedAt: '4 months ago',
798
- categoryId: 'getting-started'
799
- }]
800
- },
801
- 'student-hub': {
802
- id: 'student-hub',
803
- title: 'Student Hub',
804
- description: 'Students | Academic | Research | Discounts',
805
- iconType: 'StudentHub',
806
- articles: [{
807
- id: 'student-overview',
808
- title: 'Student Overview',
809
- description: 'Everything students need to know about using Yantra.',
810
- slug: 'student-overview',
811
- author: 'Beena',
812
- updatedAt: '4 months ago',
813
- categoryId: 'student-hub'
814
- }, {
815
- id: 'student-discounts-hub',
816
- title: 'Student Discounts',
817
- description: 'Learn about special pricing and discounts for students.',
818
- slug: 'student-discounts-hub',
819
- author: 'Beena',
820
- updatedAt: '4 months ago',
821
- categoryId: 'student-hub'
822
- }, {
823
- id: 'academic-research',
824
- title: 'Academic Research',
825
- description: 'Use Yantra for academic research and scholarly work.',
826
- slug: 'academic-research',
827
- author: 'Beena',
828
- updatedAt: '4 months ago',
829
- categoryId: 'student-hub'
830
- }, {
831
- id: 'study-tools',
832
- title: 'Study Tools',
833
- description: 'Discover study tools and features designed for students.',
834
- slug: 'study-tools',
835
- author: 'Beena',
836
- updatedAt: '4 months ago',
837
- categoryId: 'student-hub'
838
- }]
839
- },
840
- 'data-subject-privacy': {
841
- id: 'data-subject-privacy',
842
- title: 'Data Subject Privacy Requests',
843
- description: 'Privacy Requests | Data Access | Data Portability | Rights',
844
- iconType: 'DataPrivacy',
845
- articles: [{
846
- id: 'privacy-requests',
847
- title: 'Privacy Requests',
848
- description: 'How to submit privacy-related requests.',
849
- slug: 'privacy-requests',
850
- author: 'Beena',
851
- updatedAt: '4 months ago',
852
- categoryId: 'data-subject-privacy'
853
- }, {
854
- id: 'data-access',
855
- title: 'Data Access',
856
- description: 'Requesting access to your personal data.',
857
- slug: 'data-access',
858
- author: 'Beena',
859
- updatedAt: '4 months ago',
860
- categoryId: 'data-subject-privacy'
861
- }, {
862
- id: 'data-portability',
863
- title: 'Data Portability',
864
- description: 'Exporting your data for portability.',
865
- slug: 'data-portability',
866
- author: 'Beena',
867
- updatedAt: '4 months ago',
868
- categoryId: 'data-subject-privacy'
869
- }]
870
- },
871
- 'technical-questions': {
872
- id: 'technical-questions',
873
- title: 'Technical Questions',
874
- description: 'Technical | Architecture | Implementation | Development',
875
- iconType: 'TechnicalQuestions',
876
- articles: [{
877
- id: 'technical-overview',
878
- title: 'Technical Overview',
879
- description: 'Technical architecture and implementation details.',
880
- slug: 'technical-overview',
881
- author: 'Beena',
882
- updatedAt: '4 months ago',
883
- categoryId: 'technical-questions'
884
- }, {
885
- id: 'ai-models-technical',
886
- title: 'AI Models Technical',
887
- description: 'Technical details about AI model integration.',
888
- slug: 'ai-models-technical',
889
- author: 'Beena',
890
- updatedAt: '4 months ago',
891
- categoryId: 'technical-questions'
892
- }, {
893
- id: 'search-algorithms',
894
- title: 'Search Algorithms',
895
- description: "Technical details about Yantra's search algorithms.",
896
- slug: 'search-algorithms',
897
- author: 'Beena',
898
- updatedAt: '4 months ago',
899
- categoryId: 'technical-questions'
900
- }, {
901
- id: 'data-processing',
902
- title: 'Data Processing',
903
- description: 'How Yantra processes and analyzes data.',
904
- slug: 'data-processing',
905
- author: 'Beena',
906
- updatedAt: '4 months ago',
907
- categoryId: 'technical-questions'
908
- }, {
909
- id: 'infrastructure',
910
- title: 'Infrastructure',
911
- description: "Yantra's technical infrastructure and scalability.",
912
- slug: 'infrastructure',
913
- author: 'Beena',
914
- updatedAt: '4 months ago',
915
- categoryId: 'technical-questions'
916
- }, {
917
- id: 'performance-optimization',
918
- title: 'Performance Optimization',
919
- description: 'Technical optimizations for speed and efficiency.',
920
- slug: 'performance-optimization',
921
- author: 'Beena',
922
- updatedAt: '4 months ago',
923
- categoryId: 'technical-questions'
924
- }, {
925
- id: 'api-technical',
926
- title: 'API Technical',
927
- description: 'Technical details about API implementation.',
928
- slug: 'api-technical',
929
- author: 'Beena',
930
- updatedAt: '4 months ago',
931
- categoryId: 'technical-questions'
932
- }, {
933
- id: 'database-architecture',
934
- title: 'Database Architecture',
935
- description: 'Technical details about data storage and retrieval.',
936
- slug: 'database-architecture',
937
- author: 'Beena',
938
- updatedAt: '4 months ago',
939
- categoryId: 'technical-questions'
940
- }]
305
+ // Category metadata - dynamically loaded from manifest
306
+ // This will be populated from the manifest at runtime
307
+ let categoryMetadata = {};
308
+ // Initialize category metadata from manifest
309
+ async function initializeCategoryMetadata() {
310
+ if (Object.keys(categoryMetadata).length > 0) {
311
+ return; // Already initialized
941
312
  }
942
- };
313
+ const metadata = await getCategoryMetadata();
314
+ categoryMetadata = metadata;
315
+ }
316
+ // Legacy hardcoded categoryMetadata removed - now loaded dynamically from manifest
943
317
  // Process categories to include full article content and HTML
944
- const processedCategories = Object.values(categoryMetadata).map(category => ({
945
- ...category,
946
- articles: category.articles.map(articleMeta => {
947
- // For now, we'll use a placeholder content since loadMarkdownContent is async
948
- // In a real implementation, you would need to handle this differently
949
- const rawContent = `<!-- Content for ${articleMeta.id} -->`;
950
- const htmlContent = marked.parse(rawContent);
951
- const headings = extractHeadings(rawContent);
952
- return {
953
- ...articleMeta,
954
- content: rawContent,
955
- htmlContent: htmlContent,
956
- headings: headings
957
- };
958
- })
959
- }));
318
+ // This is now async and loads from manifest dynamically
319
+ let processedCategories = [];
320
+ async function initializeProcessedCategories() {
321
+ await initializeCategoryMetadata();
322
+ processedCategories = await Promise.all(Object.values(categoryMetadata).map(async category => ({
323
+ ...category,
324
+ articles: await Promise.all(category.articles.map(async articleMeta => {
325
+ // Load the actual markdown content
326
+ const contentId = articleMeta.id;
327
+ const rawContent = await loadMarkdownContent(contentId);
328
+ const {
329
+ frontmatter,
330
+ body
331
+ } = parseFrontmatter(rawContent);
332
+ const markdownBody = body || rawContent;
333
+ const htmlContent = await marked.parse(markdownBody);
334
+ const headings = extractHeadings(markdownBody);
335
+ return {
336
+ ...articleMeta,
337
+ // If metadata disagrees, prefer the markdown frontmatter (but never render it in the body)
338
+ title: frontmatter.title || articleMeta.title,
339
+ description: frontmatter.description || articleMeta.description,
340
+ author: frontmatter.author || frontmatter.authors || articleMeta.author,
341
+ updatedAt: frontmatter.updatedAt || frontmatter.date || articleMeta.updatedAt,
342
+ content: rawContent,
343
+ htmlContent: htmlContent,
344
+ headings: headings
345
+ };
346
+ }))
347
+ })));
348
+ }
349
+ // Initialize on module load (only in browser, skip during build)
350
+ // During build time, the sync functions will return empty arrays
351
+ // At runtime, the manifest will be loaded and categories will be populated
352
+ if (typeof window !== 'undefined') {
353
+ // Wait a bit for the page to fully load before initializing
354
+ if (document.readyState === 'loading') {
355
+ window.addEventListener('DOMContentLoaded', () => {
356
+ initializeProcessedCategories().catch(error => {
357
+ console.error('Error initializing processed categories:', error);
358
+ });
359
+ });
360
+ } else {
361
+ // DOM already loaded, initialize immediately
362
+ initializeProcessedCategories().catch(error => {
363
+ console.error('Error initializing processed categories:', error);
364
+ });
365
+ }
366
+ }
960
367
  // Helper functions
961
- const getAllCategoriesMetadata = () => {
368
+ const getAllCategoriesMetadata = async () => {
369
+ if (processedCategories.length === 0) {
370
+ await initializeProcessedCategories();
371
+ }
372
+ return processedCategories;
373
+ };
374
+ // Synchronous version for backward compatibility (returns empty array if not initialized)
375
+ const getAllCategoriesMetadataSync = () => {
962
376
  return processedCategories;
963
377
  };
964
- const getCategoryById = categoryId => {
378
+ const getCategoryByIdSync = categoryId => {
965
379
  return processedCategories.find(cat => cat.id === categoryId) || null;
966
380
  };
967
- const getArticleBySlug = articleSlug => {
968
- for (const category of processedCategories) {
381
+ const getArticleBySlug = async articleSlug => {
382
+ const categories = await getAllCategoriesMetadata();
383
+ for (const category of categories) {
969
384
  const article = category.articles.find(art => art.slug === articleSlug);
970
385
  if (article) return article;
971
386
  }
@@ -1007,7 +422,7 @@ function parseFrontmatter(content) {
1007
422
  }
1008
423
  // Function to load article content dynamically (for help center articles)
1009
424
  const loadArticleContent = async articleSlug => {
1010
- const article = getArticleBySlug(articleSlug);
425
+ const article = await getArticleBySlug(articleSlug);
1011
426
  if (!article) return null;
1012
427
  // Load the actual markdown content
1013
428
  const contentId = article.id;
@@ -1017,7 +432,7 @@ const loadArticleContent = async articleSlug => {
1017
432
  body
1018
433
  } = parseFrontmatter(rawContent);
1019
434
  const markdownBody = body || rawContent;
1020
- const htmlContent = marked.parse(markdownBody);
435
+ const htmlContent = await marked.parse(markdownBody);
1021
436
  const headings = extractHeadings(markdownBody);
1022
437
  return {
1023
438
  ...article,
@@ -1032,14 +447,15 @@ const loadArticleContent = async articleSlug => {
1032
447
  };
1033
448
  };
1034
449
  // Search function to find articles matching a query
1035
- const searchArticles = query => {
450
+ const searchArticles = async query => {
1036
451
  if (!query || query.trim().length === 0) {
1037
452
  return [];
1038
453
  }
1039
454
  const searchTerm = query.toLowerCase().trim();
1040
455
  const results = [];
456
+ const categories = await getAllCategoriesMetadata();
1041
457
  // Search through all categories and their articles
1042
- for (const category of processedCategories) {
458
+ for (const category of categories) {
1043
459
  for (const article of category.articles) {
1044
460
  // Search in title
1045
461
  const titleMatch = article.title.toLowerCase().includes(searchTerm);
@@ -1067,4 +483,4 @@ const searchArticles = query => {
1067
483
  return 0;
1068
484
  });
1069
485
  return results;
1070
- };export{getAllCategoriesMetadata,getArticleBySlug,getCategoryById,loadArticleContent,searchArticles};//# sourceMappingURL=markdownLoader.js.map
486
+ };export{getAllCategoriesMetadata,getAllCategoriesMetadataSync,getArticleBySlug,getCategoryByIdSync,loadArticleContent,searchArticles};//# sourceMappingURL=markdownLoader.js.map