jamdesk 1.1.69 → 1.1.71
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.
- package/dist/__tests__/integration/validate.integration.test.js +21 -0
- package/dist/__tests__/integration/validate.integration.test.js.map +1 -1
- package/dist/__tests__/unit/extract-hooks.test.js +102 -1
- package/dist/__tests__/unit/extract-hooks.test.js.map +1 -1
- package/dist/__tests__/unit/mdx-validator.test.js +22 -0
- package/dist/__tests__/unit/mdx-validator.test.js.map +1 -1
- package/dist/__tests__/unit/migrate-mdx.test.js +121 -1
- package/dist/__tests__/unit/migrate-mdx.test.js.map +1 -1
- package/dist/__tests__/unit/relative-mdx-imports.test.d.ts +2 -0
- package/dist/__tests__/unit/relative-mdx-imports.test.d.ts.map +1 -0
- package/dist/__tests__/unit/relative-mdx-imports.test.js +452 -0
- package/dist/__tests__/unit/relative-mdx-imports.test.js.map +1 -0
- package/dist/__tests__/unit/relocate-snippets.test.d.ts +2 -0
- package/dist/__tests__/unit/relocate-snippets.test.d.ts.map +1 -0
- package/dist/__tests__/unit/relocate-snippets.test.js +542 -0
- package/dist/__tests__/unit/relocate-snippets.test.js.map +1 -0
- package/dist/__tests__/unit/run-build-script.test.js +23 -1
- package/dist/__tests__/unit/run-build-script.test.js.map +1 -1
- package/dist/__tests__/unit/warn-relative-imports.test.d.ts +2 -0
- package/dist/__tests__/unit/warn-relative-imports.test.d.ts.map +1 -0
- package/dist/__tests__/unit/warn-relative-imports.test.js +44 -0
- package/dist/__tests__/unit/warn-relative-imports.test.js.map +1 -0
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +22 -8
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/migrate/convert-mdx.d.ts +5 -1
- package/dist/commands/migrate/convert-mdx.d.ts.map +1 -1
- package/dist/commands/migrate/convert-mdx.js +19 -6
- package/dist/commands/migrate/convert-mdx.js.map +1 -1
- package/dist/commands/migrate/extract-hooks.d.ts +26 -0
- package/dist/commands/migrate/extract-hooks.d.ts.map +1 -1
- package/dist/commands/migrate/extract-hooks.js +71 -12
- package/dist/commands/migrate/extract-hooks.js.map +1 -1
- package/dist/commands/migrate/fix-mdx-syntax.d.ts +38 -0
- package/dist/commands/migrate/fix-mdx-syntax.d.ts.map +1 -0
- package/dist/commands/migrate/fix-mdx-syntax.js +80 -0
- package/dist/commands/migrate/fix-mdx-syntax.js.map +1 -0
- package/dist/commands/migrate/index.d.ts.map +1 -1
- package/dist/commands/migrate/index.js +165 -3
- package/dist/commands/migrate/index.js.map +1 -1
- package/dist/commands/migrate/relocate-snippets.d.ts +30 -0
- package/dist/commands/migrate/relocate-snippets.d.ts.map +1 -0
- package/dist/commands/migrate/relocate-snippets.js +357 -0
- package/dist/commands/migrate/relocate-snippets.js.map +1 -0
- package/dist/commands/validate.d.ts.map +1 -1
- package/dist/commands/validate.js +31 -1
- package/dist/commands/validate.js.map +1 -1
- package/dist/lib/mdx-syntax-fixes.d.ts +14 -0
- package/dist/lib/mdx-syntax-fixes.d.ts.map +1 -0
- package/dist/lib/mdx-syntax-fixes.js +38 -0
- package/dist/lib/mdx-syntax-fixes.js.map +1 -0
- package/dist/lib/mdx-validator.d.ts +11 -2
- package/dist/lib/mdx-validator.d.ts.map +1 -1
- package/dist/lib/mdx-validator.js +41 -4
- package/dist/lib/mdx-validator.js.map +1 -1
- package/dist/lib/relative-mdx-imports.d.ts +44 -0
- package/dist/lib/relative-mdx-imports.d.ts.map +1 -0
- package/dist/lib/relative-mdx-imports.js +145 -0
- package/dist/lib/relative-mdx-imports.js.map +1 -0
- package/dist/lib/run-build-script.d.ts.map +1 -1
- package/dist/lib/run-build-script.js +7 -0
- package/dist/lib/run-build-script.js.map +1 -1
- package/dist/lib/warn-relative-imports.d.ts +2 -0
- package/dist/lib/warn-relative-imports.d.ts.map +1 -0
- package/dist/lib/warn-relative-imports.js +29 -0
- package/dist/lib/warn-relative-imports.js.map +1 -0
- package/package.json +1 -1
- package/vendored/app/(unlock)/jd/unlock/page.tsx +32 -0
- package/vendored/app/[[...slug]]/page.tsx +63 -15
- package/vendored/components/navigation/SocialFooter.tsx +4 -18
- package/vendored/lib/branding-url.ts +9 -0
- package/vendored/lib/layout-helpers.tsx +7 -9
- package/vendored/lib/preprocess-mdx.ts +42 -0
- package/vendored/scripts/compile-snippets.cjs +50 -7
- package/vendored/workspace-package-lock.json +3 -3
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// `NEXT_PUBLIC_PROJECT_SLUG` is read inline so Next.js inlines the value at build
|
|
2
|
+
// time for client components (SocialFooter). Hoisting the read would defeat the
|
|
3
|
+
// inline. Server components (the unlock page) just see it as runtime env.
|
|
4
|
+
export function getBrandingUrl(projectSlug?: string | null): string {
|
|
5
|
+
const slug = encodeURIComponent(
|
|
6
|
+
projectSlug || process.env.NEXT_PUBLIC_PROJECT_SLUG || 'docs'
|
|
7
|
+
);
|
|
8
|
+
return `https://www.jamdesk.com?utm_campaign=poweredBy&utm_medium=referral&utm_source=${slug}`;
|
|
9
|
+
}
|
|
@@ -234,7 +234,9 @@ export async function DocsChrome({
|
|
|
234
234
|
|
|
235
235
|
const linkPrefix = config.hostAtDocs ? '/docs' : '';
|
|
236
236
|
|
|
237
|
-
|
|
237
|
+
// Skip building the IIFE string in dev — both the script render below and
|
|
238
|
+
// the IIFE itself self-gate to non-localhost (analytics-script.ts:49).
|
|
239
|
+
const analyticsScript = process.env.NODE_ENV === 'production' && config.analytics?.enabled !== false
|
|
238
240
|
? getAnalyticsScript(resolvedProjectSlug)
|
|
239
241
|
: null;
|
|
240
242
|
|
|
@@ -449,14 +451,10 @@ export async function DocsChrome({
|
|
|
449
451
|
<HtmlLangSync defaultLanguage={projectDefaultLang} />
|
|
450
452
|
</ThemeProvider>
|
|
451
453
|
{/*
|
|
452
|
-
Inline scripts gated to production
|
|
453
|
-
React components are never executed when rendering on the
|
|
454
|
-
warning in `jamdesk dev`.
|
|
455
|
-
|
|
456
|
-
and analyticsScript self-gates to non-localhost (analytics-script.ts:49).
|
|
457
|
-
Same pattern as the project-subdomain hydration suppressor in <head>.
|
|
458
|
-
(Crisp websiteId pre-validated by regex; customJs/analyticsScript are
|
|
459
|
-
owner-controlled — same trust model as before this gate was added.)
|
|
454
|
+
Inline scripts gated to production — avoids React 19's "scripts
|
|
455
|
+
inside React components are never executed when rendering on the
|
|
456
|
+
client" warning in `jamdesk dev`. Same pattern as the
|
|
457
|
+
project-subdomain hydration suppressor in <head>.
|
|
460
458
|
*/}
|
|
461
459
|
{process.env.NODE_ENV === 'production' && config.integrations?.crisp?.websiteId &&
|
|
462
460
|
/^[a-f0-9-]{36}$/.test(config.integrations.crisp.websiteId) && (
|
|
@@ -518,6 +518,42 @@ export function normalizeJsxIndentation(content: string): string {
|
|
|
518
518
|
return result.join('\n');
|
|
519
519
|
}
|
|
520
520
|
|
|
521
|
+
/**
|
|
522
|
+
* Un-indent a closing JSX tag absorbed into the previous markdown list item.
|
|
523
|
+
*
|
|
524
|
+
* Distinct from `unindentJsxAfterListItems` below: that one rewrites indented
|
|
525
|
+
* *opening* tags inside list context. Here the opening tag is at root level
|
|
526
|
+
* and only the closing tag is indented after the list — markdown reads it as
|
|
527
|
+
* listItem continuation, so MDX compiles see the parent component as unclosed
|
|
528
|
+
* ("Expected the closing tag `</Card>` either after the end of `listItem`...").
|
|
529
|
+
*
|
|
530
|
+
* CLI mirror: `builder/cli/src/lib/mdx-syntax-fixes.ts` — keep regex in sync.
|
|
531
|
+
*/
|
|
532
|
+
export function unindentClosingTagAfterList(content: string): string {
|
|
533
|
+
// Hot-path prefilter — preprocessMdx runs on every page render, and most
|
|
534
|
+
// MDX has no indented closing tags at all. Skip the split+walk in that case.
|
|
535
|
+
if (!/^\s+<\/[A-Z]/m.test(content)) return content;
|
|
536
|
+
|
|
537
|
+
const closingTagPattern = /^(\s+)(<\/[A-Z][\w-]*>)\s*$/;
|
|
538
|
+
const listItemPattern = /^\s*(?:[-*+]\s|\d+\.\s)/;
|
|
539
|
+
const lines = content.split('\n');
|
|
540
|
+
const out: string[] = [];
|
|
541
|
+
let lastNonBlank = '';
|
|
542
|
+
|
|
543
|
+
for (const line of lines) {
|
|
544
|
+
const closing = line.match(closingTagPattern);
|
|
545
|
+
if (closing && listItemPattern.test(lastNonBlank)) {
|
|
546
|
+
out.push(closing[2]);
|
|
547
|
+
lastNonBlank = closing[2];
|
|
548
|
+
continue;
|
|
549
|
+
}
|
|
550
|
+
out.push(line);
|
|
551
|
+
if (line.trim() !== '') lastNonBlank = line;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
return out.join('\n');
|
|
555
|
+
}
|
|
556
|
+
|
|
521
557
|
/**
|
|
522
558
|
* Un-indent JSX blocks that follow markdown list items.
|
|
523
559
|
*
|
|
@@ -997,6 +1033,12 @@ export function preprocessMdx(content: string, options?: { assetVersion?: string
|
|
|
997
1033
|
// Convert noStyle to data-no-style for React compatibility
|
|
998
1034
|
processed = convertNoStyleToDataAttr(processed);
|
|
999
1035
|
|
|
1036
|
+
// Un-indent absorbed closing tags FIRST — handles the case where the
|
|
1037
|
+
// opening tag is at root level but the closing tag got indented after a
|
|
1038
|
+
// list. unindentJsxAfterListItems below only catches cases where the
|
|
1039
|
+
// opening tag itself is indented inside list context.
|
|
1040
|
+
processed = unindentClosingTagAfterList(processed);
|
|
1041
|
+
|
|
1000
1042
|
// Un-indent JSX blocks that follow list items to prevent
|
|
1001
1043
|
// "Expected closing tag before end of listItem" errors
|
|
1002
1044
|
// This must run BEFORE ensureBlankLinesInJsx since it changes block structure
|
|
@@ -321,6 +321,22 @@ export const SnippetComponents: Record<string, React.ComponentType<any>> = {};
|
|
|
321
321
|
|
|
322
322
|
const snippetFiles = findSnippetFiles(snippetsDir);
|
|
323
323
|
|
|
324
|
+
// Deterministic order: within a (dir, baseName) collision, process .mdx
|
|
325
|
+
// first so the .tsx/.jsx code file overwrites the wrapped-MDX output on
|
|
326
|
+
// disk. Without this, fs.readdir order varies by platform and the
|
|
327
|
+
// surviving file content is non-deterministic. Outside of collisions,
|
|
328
|
+
// the order doesn't matter — sort makes it stable.
|
|
329
|
+
const EXT_PRIORITY = { '.mdx': 0, '.md': 1, '.ts': 2, '.js': 3, '.tsx': 4, '.jsx': 5 };
|
|
330
|
+
snippetFiles.sort((a, b) => {
|
|
331
|
+
const aDir = path.join(a.dir, '');
|
|
332
|
+
const bDir = path.join(b.dir, '');
|
|
333
|
+
if (aDir !== bDir) return aDir < bDir ? -1 : 1;
|
|
334
|
+
const aBase = a.file.replace(/\.[^.]+$/, '');
|
|
335
|
+
const bBase = b.file.replace(/\.[^.]+$/, '');
|
|
336
|
+
if (aBase !== bBase) return aBase < bBase ? -1 : 1;
|
|
337
|
+
return (EXT_PRIORITY[path.extname(a.file)] ?? 99) - (EXT_PRIORITY[path.extname(b.file)] ?? 99);
|
|
338
|
+
});
|
|
339
|
+
|
|
324
340
|
if (snippetFiles.length === 0) {
|
|
325
341
|
console.log(' No snippet files found');
|
|
326
342
|
|
|
@@ -376,7 +392,8 @@ export const SnippetComponents: Record<string, React.ComponentType<any>> = {};
|
|
|
376
392
|
name: exportName,
|
|
377
393
|
dir: dir,
|
|
378
394
|
fileName,
|
|
379
|
-
needsClient
|
|
395
|
+
needsClient,
|
|
396
|
+
sourceFile: dir ? path.join(dir, file) : file,
|
|
380
397
|
});
|
|
381
398
|
|
|
382
399
|
const status = written ? '(updated)' : '(unchanged)';
|
|
@@ -399,7 +416,8 @@ export const SnippetComponents: Record<string, React.ComponentType<any>> = {};
|
|
|
399
416
|
name: baseName,
|
|
400
417
|
dir: dir,
|
|
401
418
|
fileName,
|
|
402
|
-
needsClient
|
|
419
|
+
needsClient,
|
|
420
|
+
sourceFile: dir ? path.join(dir, file) : file,
|
|
403
421
|
});
|
|
404
422
|
|
|
405
423
|
const status = written ? '(updated)' : '(unchanged)';
|
|
@@ -414,8 +432,33 @@ export const SnippetComponents: Record<string, React.ComponentType<any>> = {};
|
|
|
414
432
|
// For locale-specific snippets (e.g., es/Counter), we export under prefixed name (EsCounter).
|
|
415
433
|
// The buildSnippetAliasMap function handles mapping import aliases to the correct component.
|
|
416
434
|
|
|
435
|
+
// Dedupe by (dir, name): two source files with the same base name (e.g.
|
|
436
|
+
// `vercel-json-generator.mdx` + `vercel-json-generator.tsx`) compile to the
|
|
437
|
+
// same generated fileName. The on-disk file is correctly overwritten by
|
|
438
|
+
// the last writer (sorted above so code files win), but componentInfo
|
|
439
|
+
// would otherwise carry both entries and produce duplicate import/export
|
|
440
|
+
// lines in ProjectSnippets.tsx. Keep the last (= the code file).
|
|
441
|
+
const seenComponentKeys = new Map();
|
|
442
|
+
for (const c of componentInfo) {
|
|
443
|
+
const key = `${c.dir}|${c.name}`;
|
|
444
|
+
if (seenComponentKeys.has(key)) {
|
|
445
|
+
const prior = seenComponentKeys.get(key);
|
|
446
|
+
// stderr (not stdout) so `runBuildScript` surfaces this in non-verbose
|
|
447
|
+
// mode — without it, the `jamdesk dev` user sees the collision is
|
|
448
|
+
// silently resolved and the next collision (a different name) crashes
|
|
449
|
+
// Turbopack with no breadcrumb.
|
|
450
|
+
console.warn(
|
|
451
|
+
` ⚠ Snippet name collision: "${c.name}" defined in both ` +
|
|
452
|
+
`${prior.sourceFile} and ${c.sourceFile} — using ${c.sourceFile}. ` +
|
|
453
|
+
`Remove or rename one of these files to clear this warning.`,
|
|
454
|
+
);
|
|
455
|
+
}
|
|
456
|
+
seenComponentKeys.set(key, c);
|
|
457
|
+
}
|
|
458
|
+
const dedupedComponentInfo = [...seenComponentKeys.values()];
|
|
459
|
+
|
|
417
460
|
// Build unique import names for each component (prefixed with dir if needed)
|
|
418
|
-
const importInfo =
|
|
461
|
+
const importInfo = dedupedComponentInfo.map(c => {
|
|
419
462
|
const prefix = c.dir ? toPascalCase(c.dir.replace(/\//g, '-')) : '';
|
|
420
463
|
const uniqueName = prefix + c.name.charAt(0).toUpperCase() + c.name.slice(1);
|
|
421
464
|
// Strip the .tsx extension from fileName to get the import path
|
|
@@ -468,17 +511,17 @@ ${importInfo.map(c => ` ${c.uniqueName},`).join('\n')}
|
|
|
468
511
|
}
|
|
469
512
|
}
|
|
470
513
|
|
|
471
|
-
const clientCount =
|
|
472
|
-
const serverCount =
|
|
514
|
+
const clientCount = dedupedComponentInfo.filter(c => c.needsClient).length;
|
|
515
|
+
const serverCount = dedupedComponentInfo.length - clientCount;
|
|
473
516
|
|
|
474
517
|
console.log(`\n✅ Generated snippets:`);
|
|
475
518
|
console.log(` Index: ${outputPath} ${indexWritten ? '(updated)' : '(unchanged)'}`);
|
|
476
|
-
console.log(` Components: ${generatedDir}/ (${
|
|
519
|
+
console.log(` Components: ${generatedDir}/ (${dedupedComponentInfo.length} files)`);
|
|
477
520
|
if (removedCount > 0) {
|
|
478
521
|
console.log(` Removed: ${removedCount} stale file(s)`);
|
|
479
522
|
}
|
|
480
523
|
console.log(` Client components: ${clientCount}, Server components: ${serverCount}`);
|
|
481
|
-
console.log(` Exports: ${
|
|
524
|
+
console.log(` Exports: ${dedupedComponentInfo.map(c => c.name).join(', ')}\n`);
|
|
482
525
|
}
|
|
483
526
|
|
|
484
527
|
// Run the compilation
|
|
@@ -2153,9 +2153,9 @@
|
|
|
2153
2153
|
}
|
|
2154
2154
|
},
|
|
2155
2155
|
"node_modules/baseline-browser-mapping": {
|
|
2156
|
-
"version": "2.10.
|
|
2157
|
-
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.
|
|
2158
|
-
"integrity": "sha512-
|
|
2156
|
+
"version": "2.10.27",
|
|
2157
|
+
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.27.tgz",
|
|
2158
|
+
"integrity": "sha512-zEs/ufmZoUd7WftKpKyXaT6RFxpQ5Qm9xytKRHvJfxFV9DFJkZph9RvJ1LcOUi0Z1ZVijMte65JbILeV+8QQEA==",
|
|
2159
2159
|
"license": "Apache-2.0",
|
|
2160
2160
|
"bin": {
|
|
2161
2161
|
"baseline-browser-mapping": "dist/cli.cjs"
|