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.
Files changed (75) hide show
  1. package/dist/__tests__/integration/validate.integration.test.js +21 -0
  2. package/dist/__tests__/integration/validate.integration.test.js.map +1 -1
  3. package/dist/__tests__/unit/extract-hooks.test.js +102 -1
  4. package/dist/__tests__/unit/extract-hooks.test.js.map +1 -1
  5. package/dist/__tests__/unit/mdx-validator.test.js +22 -0
  6. package/dist/__tests__/unit/mdx-validator.test.js.map +1 -1
  7. package/dist/__tests__/unit/migrate-mdx.test.js +121 -1
  8. package/dist/__tests__/unit/migrate-mdx.test.js.map +1 -1
  9. package/dist/__tests__/unit/relative-mdx-imports.test.d.ts +2 -0
  10. package/dist/__tests__/unit/relative-mdx-imports.test.d.ts.map +1 -0
  11. package/dist/__tests__/unit/relative-mdx-imports.test.js +452 -0
  12. package/dist/__tests__/unit/relative-mdx-imports.test.js.map +1 -0
  13. package/dist/__tests__/unit/relocate-snippets.test.d.ts +2 -0
  14. package/dist/__tests__/unit/relocate-snippets.test.d.ts.map +1 -0
  15. package/dist/__tests__/unit/relocate-snippets.test.js +542 -0
  16. package/dist/__tests__/unit/relocate-snippets.test.js.map +1 -0
  17. package/dist/__tests__/unit/run-build-script.test.js +23 -1
  18. package/dist/__tests__/unit/run-build-script.test.js.map +1 -1
  19. package/dist/__tests__/unit/warn-relative-imports.test.d.ts +2 -0
  20. package/dist/__tests__/unit/warn-relative-imports.test.d.ts.map +1 -0
  21. package/dist/__tests__/unit/warn-relative-imports.test.js +44 -0
  22. package/dist/__tests__/unit/warn-relative-imports.test.js.map +1 -0
  23. package/dist/commands/dev.d.ts.map +1 -1
  24. package/dist/commands/dev.js +22 -8
  25. package/dist/commands/dev.js.map +1 -1
  26. package/dist/commands/migrate/convert-mdx.d.ts +5 -1
  27. package/dist/commands/migrate/convert-mdx.d.ts.map +1 -1
  28. package/dist/commands/migrate/convert-mdx.js +19 -6
  29. package/dist/commands/migrate/convert-mdx.js.map +1 -1
  30. package/dist/commands/migrate/extract-hooks.d.ts +26 -0
  31. package/dist/commands/migrate/extract-hooks.d.ts.map +1 -1
  32. package/dist/commands/migrate/extract-hooks.js +71 -12
  33. package/dist/commands/migrate/extract-hooks.js.map +1 -1
  34. package/dist/commands/migrate/fix-mdx-syntax.d.ts +38 -0
  35. package/dist/commands/migrate/fix-mdx-syntax.d.ts.map +1 -0
  36. package/dist/commands/migrate/fix-mdx-syntax.js +80 -0
  37. package/dist/commands/migrate/fix-mdx-syntax.js.map +1 -0
  38. package/dist/commands/migrate/index.d.ts.map +1 -1
  39. package/dist/commands/migrate/index.js +165 -3
  40. package/dist/commands/migrate/index.js.map +1 -1
  41. package/dist/commands/migrate/relocate-snippets.d.ts +30 -0
  42. package/dist/commands/migrate/relocate-snippets.d.ts.map +1 -0
  43. package/dist/commands/migrate/relocate-snippets.js +357 -0
  44. package/dist/commands/migrate/relocate-snippets.js.map +1 -0
  45. package/dist/commands/validate.d.ts.map +1 -1
  46. package/dist/commands/validate.js +31 -1
  47. package/dist/commands/validate.js.map +1 -1
  48. package/dist/lib/mdx-syntax-fixes.d.ts +14 -0
  49. package/dist/lib/mdx-syntax-fixes.d.ts.map +1 -0
  50. package/dist/lib/mdx-syntax-fixes.js +38 -0
  51. package/dist/lib/mdx-syntax-fixes.js.map +1 -0
  52. package/dist/lib/mdx-validator.d.ts +11 -2
  53. package/dist/lib/mdx-validator.d.ts.map +1 -1
  54. package/dist/lib/mdx-validator.js +41 -4
  55. package/dist/lib/mdx-validator.js.map +1 -1
  56. package/dist/lib/relative-mdx-imports.d.ts +44 -0
  57. package/dist/lib/relative-mdx-imports.d.ts.map +1 -0
  58. package/dist/lib/relative-mdx-imports.js +145 -0
  59. package/dist/lib/relative-mdx-imports.js.map +1 -0
  60. package/dist/lib/run-build-script.d.ts.map +1 -1
  61. package/dist/lib/run-build-script.js +7 -0
  62. package/dist/lib/run-build-script.js.map +1 -1
  63. package/dist/lib/warn-relative-imports.d.ts +2 -0
  64. package/dist/lib/warn-relative-imports.d.ts.map +1 -0
  65. package/dist/lib/warn-relative-imports.js +29 -0
  66. package/dist/lib/warn-relative-imports.js.map +1 -0
  67. package/package.json +1 -1
  68. package/vendored/app/(unlock)/jd/unlock/page.tsx +32 -0
  69. package/vendored/app/[[...slug]]/page.tsx +63 -15
  70. package/vendored/components/navigation/SocialFooter.tsx +4 -18
  71. package/vendored/lib/branding-url.ts +9 -0
  72. package/vendored/lib/layout-helpers.tsx +7 -9
  73. package/vendored/lib/preprocess-mdx.ts +42 -0
  74. package/vendored/scripts/compile-snippets.cjs +50 -7
  75. package/vendored/workspace-package-lock.json +3 -3
@@ -10,6 +10,7 @@ import { homedir } from 'os';
10
10
  import { createRequire } from 'module';
11
11
  import { pathToFileURL } from 'url';
12
12
  import { preprocessFrontmatter } from './frontmatter-utils.js';
13
+ import { unindentClosingTagsAfterLists } from './mdx-syntax-fixes.js';
13
14
  let cachedMdx = null;
14
15
  /**
15
16
  * Build the user-facing error thrown when @mdx-js/mdx can't be resolved.
@@ -43,9 +44,17 @@ async function importMdx() {
43
44
  return cachedMdx;
44
45
  }
45
46
  /**
46
- * Validate a single MDX file's content
47
+ * Validate a single MDX file's content.
48
+ *
49
+ * @param applySyntaxFixes - Whether to apply the same in-memory rewrites
50
+ * that build-service's preprocessMdx pipeline applies at render time
51
+ * (e.g. unindenting closing tags absorbed by list items). Default `true`
52
+ * so dev's gate matches what actually compiles. Pass `false` to see the
53
+ * verdict against raw on-disk content — used by `jamdesk migrate` to
54
+ * detect files that *would* break without the runtime safety net.
47
55
  */
48
- export async function validateMdxFile(content, filePath) {
56
+ export async function validateMdxFile(content, filePath, options = {}) {
57
+ const { applySyntaxFixes = true } = options;
49
58
  const { compile } = await importMdx();
50
59
  const matter = (await import('gray-matter')).default;
51
60
  // Pre-process frontmatter to handle common issues
@@ -61,9 +70,13 @@ export async function validateMdxFile(content, filePath) {
61
70
  suggestion: 'Check YAML syntax between --- markers',
62
71
  };
63
72
  }
64
- // Step 2: Validate MDX syntax
73
+ // Step 2: Validate MDX syntax. By default, mirror the runtime preprocess
74
+ // pipeline so dev's gate matches what gets compiled at request time.
75
+ const toCompile = applySyntaxFixes
76
+ ? unindentClosingTagsAfterLists(processedContent).content
77
+ : processedContent;
65
78
  try {
66
- await compile(processedContent, { jsx: true });
79
+ await compile(toCompile, { jsx: true });
67
80
  return null; // Valid
68
81
  }
69
82
  catch (err) {
@@ -97,6 +110,10 @@ export function extractAllPages(navigation) {
97
110
  if ('tabs' in item && Array.isArray(item.tabs)) {
98
111
  processItems(item.tabs);
99
112
  }
113
+ // Handle dropdowns (Mintlify navigation grouping)
114
+ if ('dropdowns' in item && Array.isArray(item.dropdowns)) {
115
+ processItems(item.dropdowns);
116
+ }
100
117
  }
101
118
  }
102
119
  }
@@ -119,6 +136,15 @@ export function extractAllPages(navigation) {
119
136
  if (navigation.groups && Array.isArray(navigation.groups)) {
120
137
  processItems(navigation.groups);
121
138
  }
139
+ // Handle pages structure: { pages: [...] } — produced by
140
+ // convertMintlifyToJamdesk when the source had a top-level navigation array.
141
+ if (navigation.pages && Array.isArray(navigation.pages)) {
142
+ processItems(navigation.pages);
143
+ }
144
+ // Handle top-level dropdowns: { dropdowns: [...] }
145
+ if (navigation.dropdowns && Array.isArray(navigation.dropdowns)) {
146
+ processItems(navigation.dropdowns);
147
+ }
122
148
  // Handle flat array: [...]
123
149
  if (Array.isArray(navigation)) {
124
150
  processItems(navigation);
@@ -168,6 +194,17 @@ function formatMdxError(err, filePath) {
168
194
  suggestion =
169
195
  'A < character is being parsed as JSX. Use &lt; or rewrite (e.g., "Below 50%" instead of "<50%")';
170
196
  }
197
+ else if (message.includes('Expected the closing tag') &&
198
+ message.includes('listItem')) {
199
+ // Indented closing tags get absorbed into the previous list item:
200
+ // - last bullet
201
+ // </Card> ← 2-space indent makes this part of the listItem
202
+ // The fix is always to unindent the closing tag flush-left (or
203
+ // separate it from the list with a blank line).
204
+ suggestion =
205
+ 'Closing tag is indented and got absorbed into the preceding list item. ' +
206
+ 'Unindent the closing tag flush-left, or add a blank line between the last list item and the closing tag.';
207
+ }
171
208
  else if (message.includes('Expected closing tag')) {
172
209
  suggestion = 'Add the missing closing tag or use self-closing syntax (<Component />)';
173
210
  }
@@ -1 +1 @@
1
- {"version":3,"file":"mdx-validator.js","sourceRoot":"","sources":["../../src/lib/mdx-validator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mdx-validator.js","sourceRoot":"","sources":["../../src/lib/mdx-validator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Detect and rewrite parent-relative MDX imports.
3
+ *
4
+ * Mintlify supports `import X from '../snippets/foo.mdx'`; Jamdesk only
5
+ * resolves root-relative `import X from '/snippets/foo.mdx'`. The
6
+ * detector finds candidates; the rewriter fixes the ones that resolve
7
+ * under a `snippets/` directory (conservative — see plan).
8
+ */
9
+ export interface RelativeMdxImport {
10
+ /** The import specifier as written, e.g. '../snippets/foo.mdx'. */
11
+ specifier: string;
12
+ /** 1-indexed line number in the source. */
13
+ line: number;
14
+ /** The full matched import statement (for replacement). */
15
+ raw: string;
16
+ }
17
+ export declare function stripFencedCodeBlocks(content: string): string;
18
+ /**
19
+ * Pass `alreadyStripped: true` when the caller already ran
20
+ * `stripFencedCodeBlocks` — avoids redoing the regex pass when the same
21
+ * stripped content drives multiple analyses (e.g. link extraction +
22
+ * import detection during relocation).
23
+ */
24
+ export declare function detectRelativeMdxImports(content: string, alreadyStripped?: boolean): RelativeMdxImport[];
25
+ export interface RewriteResult {
26
+ /** Content with applicable imports rewritten. */
27
+ content: string;
28
+ /** Specifiers that were successfully rewritten. */
29
+ rewrites: {
30
+ from: string;
31
+ to: string;
32
+ line: number;
33
+ }[];
34
+ /** Human-readable warnings for imports left untouched. */
35
+ warnings: string[];
36
+ }
37
+ /**
38
+ * Rewrite parent-relative MDX imports to root-relative `/snippets/*` form
39
+ * when the resolved target sits under a top-level `snippets/` directory.
40
+ * Imports that resolve elsewhere (siblings, non-existent files, paths
41
+ * outside `projectRoot`) are left untouched and reported in `warnings`.
42
+ */
43
+ export declare function rewriteRelativeMdxImports(content: string, filePath: string, projectRoot: string): Promise<RewriteResult>;
44
+ //# sourceMappingURL=relative-mdx-imports.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relative-mdx-imports.d.ts","sourceRoot":"","sources":["../../src/lib/relative-mdx-imports.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AAEH,MAAM,WAAW,iBAAiB;IAChC,mEAAmE;IACnE,SAAS,EAAE,MAAM,CAAC;IAClB,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,GAAG,EAAE,MAAM,CAAC;CACb;AA8BD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAQ7D;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,MAAM,EACf,eAAe,UAAQ,GACtB,iBAAiB,EAAE,CAiBrB;AAED,MAAM,WAAW,aAAa;IAC5B,iDAAiD;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACvD,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,aAAa,CAAC,CA0FxB"}
@@ -0,0 +1,145 @@
1
+ // builder/cli/src/lib/relative-mdx-imports.ts
2
+ import fs from 'fs-extra';
3
+ import path from 'node:path';
4
+ // Captures: import <binding> from '<./or../><path>.mdx';
5
+ // Quotes: single or double. Named: { Foo, Bar } (multi-line ok). Default: Foo.
6
+ // Namespace: * as Foo. Type-only: import type X. Combined: Default, { Named }.
7
+ // Side-effect imports (`import "..mdx"` with no binding) are intentionally
8
+ // ignored — MDX needs a binding to render the snippet.
9
+ //
10
+ // Anchored to start-of-line (with `gm` + `^[ \t]*`) so the regex can't match
11
+ // the literal English word "import" inside a heading or prose paragraph and
12
+ // then bridge across multiple lines to the real import — that produced wrong
13
+ // `line` numbers in user-facing warnings (validate/dev print `<file>:<line>`).
14
+ //
15
+ // The binding character class allows identifiers, `$`, `*` (namespace), commas,
16
+ // braces, spaces, and newlines (for multi-line `{ ... }` lists). It explicitly
17
+ // excludes quotes and slashes so the bridge can't extend past the next `"` or
18
+ // jump into a sibling import on a later line.
19
+ const RELATIVE_MDX_IMPORT_RE = /^[ \t]*import\s+(?:type\s+)?[\w$*{}, \n\r]+\s+from\s+["'](\.{1,2}\/[^"']+\.mdx)["']\s*;?/gm;
20
+ // Replaces fenced code-block bodies with same-shape blanks so line numbers are
21
+ // preserved but imports inside fences don't match. Handles both ``` and ~~~
22
+ // fences with optional info strings (e.g. ```mdx shared/example.mdx wrap).
23
+ // Indent class is `( *)` (not the CommonMark `{0,3}`) so we also catch fences
24
+ // nested in numbered list items / `<CodeGroup>` blocks where the fence opens
25
+ // at column 4+ (real Mintlify pattern in `create/reusable-snippets.mdx`).
26
+ // The capture binds `\1` to the exact indent so the close has to match.
27
+ const FENCED_CODE_BLOCK_RE = /^( *)(```+|~~~+)[^\n]*\n([\s\S]*?)\n\1\2\s*$/gm;
28
+ export function stripFencedCodeBlocks(content) {
29
+ return content.replace(FENCED_CODE_BLOCK_RE, (match, _indent, _fence, body) => {
30
+ // Replace body with blank lines of same count to preserve line numbers.
31
+ const bodyLines = body.split('\n').length;
32
+ const fenceOpen = match.split('\n')[0];
33
+ const fenceClose = match.split('\n').slice(-1)[0];
34
+ return [fenceOpen, ...Array(bodyLines).fill(''), fenceClose].join('\n');
35
+ });
36
+ }
37
+ /**
38
+ * Pass `alreadyStripped: true` when the caller already ran
39
+ * `stripFencedCodeBlocks` — avoids redoing the regex pass when the same
40
+ * stripped content drives multiple analyses (e.g. link extraction +
41
+ * import detection during relocation).
42
+ */
43
+ export function detectRelativeMdxImports(content, alreadyStripped = false) {
44
+ const stripped = alreadyStripped ? content : stripFencedCodeBlocks(content);
45
+ const out = [];
46
+ RELATIVE_MDX_IMPORT_RE.lastIndex = 0;
47
+ let match;
48
+ while ((match = RELATIVE_MDX_IMPORT_RE.exec(stripped)) !== null) {
49
+ const before = stripped.slice(0, match.index);
50
+ // 1-indexed line of the `import` keyword. Line numbers preserved by
51
+ // stripFencedCodeBlocks (replaces body with same-count blank lines).
52
+ const line = before.split('\n').length;
53
+ out.push({
54
+ specifier: match[1],
55
+ line,
56
+ raw: match[0],
57
+ });
58
+ }
59
+ return out;
60
+ }
61
+ /**
62
+ * Rewrite parent-relative MDX imports to root-relative `/snippets/*` form
63
+ * when the resolved target sits under a top-level `snippets/` directory.
64
+ * Imports that resolve elsewhere (siblings, non-existent files, paths
65
+ * outside `projectRoot`) are left untouched and reported in `warnings`.
66
+ */
67
+ export async function rewriteRelativeMdxImports(content, filePath, projectRoot) {
68
+ const matches = detectRelativeMdxImports(content);
69
+ const rewrites = [];
70
+ const warnings = [];
71
+ const fileDir = path.dirname(filePath);
72
+ const snippetsRoot = path.join(projectRoot, 'snippets');
73
+ const relPath = path.relative(projectRoot, filePath);
74
+ let next = content;
75
+ for (const m of matches) {
76
+ const resolved = path.resolve(fileDir, m.specifier);
77
+ if (!(await fs.pathExists(resolved))) {
78
+ // Resume-after-partial: a previous relocate run may have moved the
79
+ // file to `/snippets/<sameRel>` while leaving this importer's path
80
+ // untouched (e.g. user manually moved files, or relocate aborted
81
+ // mid-flight on a second pass). The relocator preserves source-dir
82
+ // structure when moving, so probing `snippets/<resolved-rel>` is
83
+ // the inverse of that move and cheaply makes re-runs idempotent.
84
+ const resolvedRel = path.relative(projectRoot, resolved);
85
+ if (!resolvedRel.startsWith('..') &&
86
+ !path.isAbsolute(resolvedRel) &&
87
+ !resolvedRel.startsWith(`snippets${path.sep}`)) {
88
+ const movedCandidate = path.join(snippetsRoot, resolvedRel);
89
+ if (await fs.pathExists(movedCandidate)) {
90
+ const newSpec = `/snippets/${resolvedRel.replaceAll(path.sep, '/')}`;
91
+ // Replacer functions (not strings) — `$` in user paths would
92
+ // otherwise be interpreted as String.replace backreferences.
93
+ const newImport = m.raw.replace(m.specifier, () => newSpec);
94
+ next = next.replace(m.raw, () => newImport);
95
+ rewrites.push({ from: m.specifier, to: newSpec, line: m.line });
96
+ continue;
97
+ }
98
+ }
99
+ // Mintlify-style root-snippets fallback. `../snippets/X` from `zh/folder/`
100
+ // resolves literally to `zh/snippets/X` (doesn't exist), but the user
101
+ // almost always meant `<root>/snippets/X` — Mintlify resolves it that
102
+ // way regardless of depth, and localized pages copy the import verbatim.
103
+ const rootSnippetMatch = m.specifier.match(/^(?:\.\.\/)+snippets\/(.+\.mdx)$/);
104
+ if (rootSnippetMatch) {
105
+ const rootCandidate = path.join(snippetsRoot, rootSnippetMatch[1]);
106
+ if (await fs.pathExists(rootCandidate)) {
107
+ const newSpec = `/snippets/${rootSnippetMatch[1]}`;
108
+ const newImport = m.raw.replace(m.specifier, () => newSpec);
109
+ next = next.replace(m.raw, () => newImport);
110
+ rewrites.push({ from: m.specifier, to: newSpec, line: m.line });
111
+ continue;
112
+ }
113
+ }
114
+ warnings.push(`${relPath}:${m.line}: ${m.specifier} — target file doesn't exist; ` +
115
+ `create the snippet or remove this import`);
116
+ continue;
117
+ }
118
+ const rel = path.relative(snippetsRoot, resolved);
119
+ if (rel.startsWith('..') || path.isAbsolute(rel)) {
120
+ // Target exists but isn't under /snippets/. The user has to decide.
121
+ const targetRel = path.relative(projectRoot, resolved);
122
+ const suggestedSnippetPath = `/snippets/${path.basename(resolved)}`;
123
+ // If the suggested destination already holds a different file,
124
+ // saying "Move the file to <X>" would clobber. Surface the conflict
125
+ // so the user knows to rename or merge instead.
126
+ const collision = await fs.pathExists(path.join(snippetsRoot, path.basename(resolved)));
127
+ if (collision) {
128
+ warnings.push(`${relPath}:${m.line}: ${m.specifier} → ${targetRel} is not under /snippets/, ` +
129
+ `but ${suggestedSnippetPath} already exists with different content. ` +
130
+ `Rename one of the files or inline this import.`);
131
+ }
132
+ else {
133
+ warnings.push(`${relPath}:${m.line}: ${m.specifier} → ${targetRel} is not under /snippets/. ` +
134
+ `Move the file to ${suggestedSnippetPath} (and update this import) or inline its content.`);
135
+ }
136
+ continue;
137
+ }
138
+ const newSpec = `/snippets/${rel.replaceAll(path.sep, '/')}`;
139
+ const newImport = m.raw.replace(m.specifier, () => newSpec);
140
+ next = next.replace(m.raw, () => newImport);
141
+ rewrites.push({ from: m.specifier, to: newSpec, line: m.line });
142
+ }
143
+ return { content: next, rewrites, warnings };
144
+ }
145
+ //# sourceMappingURL=relative-mdx-imports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relative-mdx-imports.js","sourceRoot":"","sources":["../../src/lib/relative-mdx-imports.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"run-build-script.d.ts","sourceRoot":"","sources":["../../src/lib/run-build-script.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAOD,wBAAsB,cAAc,CAClC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GACjE,OAAO,CAAC,YAAY,CAAC,CAgBvB;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,EAAE,EACjB,OAAO,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GACjE,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,YAAY,EAAE,CAAA;CAAE,CAAC,CAIjE"}
1
+ {"version":3,"file":"run-build-script.d.ts","sourceRoot":"","sources":["../../src/lib/run-build-script.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAOD,wBAAsB,cAAc,CAClC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GACjE,OAAO,CAAC,YAAY,CAAC,CAsBvB;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,EAAE,EACjB,OAAO,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GACjE,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,YAAY,EAAE,CAAA;CAAE,CAAC,CAIjE"}
@@ -31,6 +31,13 @@ export async function runBuildScript(script, options) {
31
31
  if (stderr)
32
32
  process.stderr.write(stderr);
33
33
  }
34
+ else if (stderr) {
35
+ // Successful scripts that wrote to stderr signalled a non-fatal warning
36
+ // (e.g. compile-snippets snippet-name collision). Surfacing these even
37
+ // in non-verbose mode means the next dev start doesn't blow up
38
+ // mysteriously when the warning's resolution lapses.
39
+ process.stderr.write(stderr);
40
+ }
34
41
  return { script, success: true };
35
42
  }
36
43
  catch (error) {
@@ -1 +1 @@
1
- {"version":3,"file":"run-build-script.js","sourceRoot":"","sources":["../../src/lib/run-build-script.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AAEjC,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;AAUlC,qEAAqE;AACrE,iDAAiD;AACjD,uDAAuD;AACvD,MAAM,UAAU,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAEpC,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAc,EACd,OAAkE;IAElE,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,gBAAgB,MAAM,EAAE,EAAE;YACnE,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,SAAS,EAAE,UAAU;SACtB,CAAC,CAAC;QACH,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,IAAI,MAAM;gBAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACzC,IAAI,MAAM;gBAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC3C,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACnC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,GAAG,KAA6C,CAAC;QACxD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC;IAC/E,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,OAAiB,EACjB,OAAkE;IAElE,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAClF,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IACnD,OAAO,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AACxE,CAAC"}
1
+ {"version":3,"file":"run-build-script.js","sourceRoot":"","sources":["../../src/lib/run-build-script.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AAEjC,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;AAUlC,qEAAqE;AACrE,iDAAiD;AACjD,uDAAuD;AACvD,MAAM,UAAU,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAEpC,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAc,EACd,OAAkE;IAElE,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,gBAAgB,MAAM,EAAE,EAAE;YACnE,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,SAAS,EAAE,UAAU;SACtB,CAAC,CAAC;QACH,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,IAAI,MAAM;gBAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACzC,IAAI,MAAM;gBAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC3C,CAAC;aAAM,IAAI,MAAM,EAAE,CAAC;YAClB,wEAAwE;YACxE,uEAAuE;YACvE,+DAA+D;YAC/D,qDAAqD;YACrD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC/B,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACnC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,GAAG,KAA6C,CAAC;QACxD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC;IAC/E,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,OAAiB,EACjB,OAAkE;IAElE,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAClF,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IACnD,OAAO,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AACxE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function warnOnRelativeMdxImports(projectDir: string): Promise<number>;
2
+ //# sourceMappingURL=warn-relative-imports.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"warn-relative-imports.d.ts","sourceRoot":"","sources":["../../src/lib/warn-relative-imports.ts"],"names":[],"mappings":"AAIA,wBAAsB,wBAAwB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA0BlF"}
@@ -0,0 +1,29 @@
1
+ import { glob } from 'glob';
2
+ import { readFile } from 'node:fs/promises';
3
+ import { detectRelativeMdxImports } from './relative-mdx-imports.js';
4
+ export async function warnOnRelativeMdxImports(projectDir) {
5
+ const files = await glob('**/*.mdx', {
6
+ cwd: projectDir,
7
+ ignore: ['**/node_modules/**', '**/.git/**'],
8
+ absolute: true,
9
+ });
10
+ let offending = 0;
11
+ for (const file of files) {
12
+ try {
13
+ const content = await readFile(file, 'utf-8');
14
+ if (detectRelativeMdxImports(content).length > 0)
15
+ offending++;
16
+ }
17
+ catch {
18
+ // unreadable file — skip
19
+ }
20
+ }
21
+ if (offending > 0) {
22
+ console.warn(`\n⚠ Found ${offending} MDX file(s) with parent-relative imports. ` +
23
+ `Run "jamdesk migrate" to auto-fix; "jamdesk validate" lists each one with the ` +
24
+ `specific manual action when migrate can't help. Pages with these imports will ` +
25
+ `fail to compile.\n`);
26
+ }
27
+ return offending;
28
+ }
29
+ //# sourceMappingURL=warn-relative-imports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"warn-relative-imports.js","sourceRoot":"","sources":["../../src/lib/warn-relative-imports.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAErE,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,UAAkB;IAC/D,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE;QACnC,GAAG,EAAE,UAAU;QACf,MAAM,EAAE,CAAC,oBAAoB,EAAE,YAAY,CAAC;QAC5C,QAAQ,EAAE,IAAI;KACf,CAAC,CAAC;IAEH,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC9C,IAAI,wBAAwB,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC;gBAAE,SAAS,EAAE,CAAC;QAChE,CAAC;QAAC,MAAM,CAAC;YACP,yBAAyB;QAC3B,CAAC;IACH,CAAC;IAED,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;QAClB,OAAO,CAAC,IAAI,CACV,aAAa,SAAS,6CAA6C;YACnE,gFAAgF;YAChF,gFAAgF;YAChF,oBAAoB,CACrB,CAAC;IACJ,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jamdesk",
3
- "version": "1.1.69",
3
+ "version": "1.1.71",
4
4
  "description": "CLI for Jamdesk — build, preview, and deploy documentation sites from MDX. Dev server with hot reload, 50+ components, OpenAPI support, AI search, and Mintlify migration",
5
5
  "keywords": [
6
6
  "jamdesk",
@@ -2,6 +2,7 @@ import { headers } from 'next/headers';
2
2
  import { getDocsConfig } from '@/lib/docs-isr';
3
3
  import { normalizeLogo } from '@/lib/docs-types';
4
4
  import { sanitizeFrom } from '@/lib/sanitize-from';
5
+ import { getBrandingUrl } from '@/lib/branding-url';
5
6
  import UnlockForm from './UnlockForm';
6
7
 
7
8
  interface UnlockPageProps {
@@ -29,14 +30,19 @@ export default async function UnlockPage({ searchParams }: UnlockPageProps) {
29
30
  const from = sanitizeFrom(rawFrom ?? null);
30
31
  const showError = params.error === '1';
31
32
 
33
+ const showBranding = process.env.NEXT_PUBLIC_SHOW_BRANDING !== 'false';
34
+ const brandingUrl = getBrandingUrl(slug);
35
+
32
36
  return (
33
37
  <main
34
38
  style={{
35
39
  minHeight: '100vh',
36
40
  display: 'flex',
41
+ flexDirection: 'column',
37
42
  alignItems: 'center',
38
43
  justifyContent: 'center',
39
44
  padding: '24px 16px',
45
+ gap: 24,
40
46
  }}
41
47
  >
42
48
  <section
@@ -152,6 +158,32 @@ export default async function UnlockPage({ searchParams }: UnlockPageProps) {
152
158
  </p>
153
159
  )}
154
160
  </section>
161
+
162
+ {showBranding && (
163
+ <a
164
+ href={brandingUrl}
165
+ target="_blank"
166
+ rel="noopener noreferrer"
167
+ style={{
168
+ display: 'inline-flex',
169
+ alignItems: 'center',
170
+ gap: 6,
171
+ fontSize: 13,
172
+ color: '#9ca3af',
173
+ textDecoration: 'none',
174
+ }}
175
+ >
176
+ Powered by
177
+ {/* eslint-disable-next-line @next/next/no-img-element */}
178
+ <img
179
+ src="/_jd/branding/jamdesk-wordmark.svg"
180
+ alt="Jamdesk"
181
+ width={58}
182
+ height={15}
183
+ style={{ display: 'inline-block', verticalAlign: 'middle' }}
184
+ />
185
+ </a>
186
+ )}
155
187
  </main>
156
188
  );
157
189
  }
@@ -25,54 +25,102 @@ interface PageProps {
25
25
  }>;
26
26
  }
27
27
 
28
- function getAllDocPaths(): string[] {
28
+ // Mirror of the CLI's detector regex in cli/src/lib/relative-mdx-imports.ts.
29
+ // Duplicated intentionally — build-service uses bundler module resolution
30
+ // and shouldn't reach into cli/src/. Keep the regex itself in sync with
31
+ // that file. Two intentional simplifications vs the CLI version:
32
+ // - no `g` flag (boolean test, not iteration)
33
+ // - fence stripping replaces matches with empty string instead of
34
+ // blank lines of equal count — line numbers don't matter here, only
35
+ // a yes/no skip decision (the CLI preserves them for warning text).
36
+ const PARENT_RELATIVE_MDX_IMPORT_RE =
37
+ /^[ \t]*import\s+(?:type\s+)?[\w$*{}, \n\r]+\s+from\s+["']\.{1,2}\/[^"']+\.mdx["']\s*;?/m;
38
+
39
+ const FENCED_CODE_BLOCK_RE =
40
+ /^( *)(```+|~~~+)[^\n]*\n([\s\S]*?)\n\1\2\s*$/gm;
41
+
42
+ export function pageHasRelativeMdxImport(filePath: string): boolean {
43
+ try {
44
+ // Read the full file — MDX imports can appear at any top-level position
45
+ // (after a long prose intro or table of contents), and a slice was
46
+ // missing real imports past byte ~8192 in 70-94 KB customer pages.
47
+ const content = fs.readFileSync(filePath, 'utf-8');
48
+ // Strip fenced code blocks so documentation examples (e.g.
49
+ // ```mdx\nimport X from "../snippets/foo.mdx";\n```) don't false-trigger.
50
+ return PARENT_RELATIVE_MDX_IMPORT_RE.test(content.replace(FENCED_CODE_BLOCK_RE, ''));
51
+ } catch {
52
+ return false;
53
+ }
54
+ }
55
+
56
+ interface CollectedPaths {
57
+ supported: string[];
58
+ skipped: string[];
59
+ }
60
+
61
+ function getAllDocPaths(): CollectedPaths {
29
62
  const contentDir = getContentDir();
30
- const paths: string[] = [];
63
+ const supported: string[] = [];
64
+ const skipped: string[] = [];
31
65
 
32
66
  function traverseDir(dir: string, basePath: string = '') {
33
67
  if (!fs.existsSync(dir)) return;
34
68
  const files = fs.readdirSync(dir);
35
69
  for (const file of files) {
36
- // Skip dotfiles (.claude, .git, etc.)
37
70
  if (file.startsWith('.')) continue;
38
71
  const filePath = path.join(dir, file);
39
72
  let stat;
40
73
  try {
41
74
  stat = fs.statSync(filePath);
42
75
  } catch {
43
- // Broken symlink or inaccessible — skip
44
76
  continue;
45
77
  }
46
78
  if (stat.isDirectory()) {
47
79
  traverseDir(filePath, path.join(basePath, file));
48
80
  } else if (file.endsWith('.mdx')) {
49
81
  const slug = path.join(basePath, file.replace(/\.mdx$/, ''));
50
- paths.push(slug);
82
+ if (pageHasRelativeMdxImport(filePath)) {
83
+ skipped.push(slug);
84
+ } else {
85
+ supported.push(slug);
86
+ }
51
87
  }
52
88
  }
53
89
  }
54
90
 
55
91
  traverseDir(contentDir);
56
- return paths;
92
+ return { supported, skipped };
57
93
  }
58
94
 
95
+ // In `jamdesk dev`, Next.js calls generateStaticParams during initial
96
+ // compile AND for each lazily-compiled route (every page click). Without
97
+ // a guard the same multi-line warning floods the dev console after every
98
+ // navigation. Cache the prior skipped set and re-log only when it changes
99
+ // — that way a user who fixes one import still sees the list shrink, but
100
+ // repeated calls with no change stay quiet.
101
+ let lastSkippedKey: string | null = null;
102
+
59
103
  export async function generateStaticParams() {
60
104
  // ISR: pages generated on-demand, no build-time pre-render.
61
105
  if (isIsrMode()) return [];
62
106
 
63
- const paths = getAllDocPaths();
64
- // next-mdx-remote can't compile relative MDX imports — skip those tests.
65
- const unsupportedPatterns = ['deep-relative-test', 'relative-snippets-test'];
107
+ const { supported, skipped } = getAllDocPaths();
66
108
 
67
- const supportedPaths = paths.filter(p => {
68
- const skip = unsupportedPatterns.some(pattern => p.includes(pattern));
69
- if (skip) console.log(`[Build] Skipping page with unsupported relative imports: ${p}`);
70
- return !skip;
71
- });
109
+ const skippedKey = skipped.length === 0 ? '' : skipped.slice().sort().join('\n');
110
+ if (skippedKey !== lastSkippedKey) {
111
+ lastSkippedKey = skippedKey;
112
+ if (skipped.length > 0) {
113
+ console.log(`[Build] Skipped ${skipped.length} page(s) with parent-relative MDX imports:`);
114
+ for (const slug of skipped) {
115
+ console.log(` - ${slug}`);
116
+ }
117
+ console.log(' Run "jamdesk migrate" to auto-fix moveable imports, or "jamdesk validate" for per-import detail.');
118
+ }
119
+ }
72
120
 
73
121
  return [
74
122
  { slug: [] },
75
- ...supportedPaths.map((p) => ({ slug: p.split('/') })),
123
+ ...supported.map((p) => ({ slug: p.split('/') })),
76
124
  ];
77
125
  }
78
126
 
@@ -3,19 +3,9 @@
3
3
  import Image from 'next/image';
4
4
  import type { DocsConfig, SocialPlatform, FooterLinkColumn } from '@/lib/docs-types';
5
5
  import { getIconClass } from '@/lib/icon-utils';
6
+ import { getBrandingUrl } from '@/lib/branding-url';
6
7
 
7
- // Branding configuration (read at build time from environment variables)
8
- // Uses NEXT_PUBLIC_ prefix so these are inlined during build for client components
9
- const showBranding = process.env.NEXT_PUBLIC_SHOW_BRANDING !== 'false'; // Default true
10
-
11
- /**
12
- * Generate branding URL with UTM parameters for attribution tracking.
13
- * projectSlug is passed as a prop (works in ISR multi-tenant mode).
14
- * Falls back to NEXT_PUBLIC_PROJECT_SLUG env var (works in CLI dev mode).
15
- */
16
- function getBrandingUrl(projectSlug: string): string {
17
- return `https://www.jamdesk.com?utm_campaign=poweredBy&utm_medium=referral&utm_source=${projectSlug}`;
18
- }
8
+ const showBranding = process.env.NEXT_PUBLIC_SHOW_BRANDING !== 'false';
19
9
 
20
10
  interface SocialFooterProps {
21
11
  config: DocsConfig;
@@ -150,23 +140,19 @@ export function SocialFooter({ config, hidden, projectSlug }: SocialFooterProps)
150
140
  return null;
151
141
  }
152
142
 
153
- // Resolve slug: prop (ISR) → env var (CLI dev) → fallback
154
- const slug = projectSlug || process.env.NEXT_PUBLIC_PROJECT_SLUG || 'docs';
155
-
156
143
  return (
157
144
  <footer className="mt-12 sm:mt-16 pt-6 sm:pt-8 border-t border-[var(--color-border)]">
158
145
  {hasLinks && <LinkColumns columns={links} />}
159
- {/* Desktop: row layout, Mobile: column layout */}
160
146
  <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
161
147
  {hasSocials && <SocialIcons socials={socials} />}
162
148
  {showBranding && (
163
149
  <a
164
- href={getBrandingUrl(slug)}
150
+ href={getBrandingUrl(projectSlug)}
165
151
  target="_blank"
166
152
  rel="noopener noreferrer"
167
153
  className="group flex items-center gap-1 text-sm text-[#AEAEAE] hover:text-[#6A6D70] transition-colors whitespace-nowrap"
168
154
  >
169
- <span>Powered by</span>
155
+ Powered by
170
156
  <span className="relative inline-block w-[58px] h-[15px] top-[1px]">
171
157
  <Image
172
158
  src="/_jd/branding/jamdesk-wordmark.svg"