@sudajs/cli 0.12.3 → 0.13.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sudajs/cli",
3
- "version": "0.12.3",
3
+ "version": "0.13.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "suda": "./bin/suda.js"
@@ -34,7 +34,7 @@
34
34
  "react": "^19.2.7",
35
35
  "react-dom": "^19.2.7",
36
36
  "zod": "^3.24.1",
37
- "@sudajs/theme-engine": "4.0.2"
37
+ "@sudajs/theme-engine": "5.1.0"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@tailwindcss/postcss": "^4.3.0",
@@ -139,7 +139,7 @@ Field source of truth:
139
139
  generation reliable.
140
140
  - Use `description`, `placeholder`, and `visibleIf` only when they help the
141
141
  editor or AI choose the right value.
142
- - Suda extended field types are `url`, `icon`, `font`, `menu`, `color`,
142
+ - Suda extended field types are `url`, `icon`, `color`,
143
143
  `range`, `spacing`, `media`, `image`, `video`, and `posts`. These are valid
144
144
  in `fields` and are normalized by `@sudajs/theme-engine`.
145
145
 
@@ -189,8 +189,6 @@ fields: {
189
189
  download: { type: "media", kind: "file", label: t("common.fields.file") },
190
190
  icon: { type: "icon", label: t("common.fields.icon") },
191
191
  accentColor: { type: "color", label: t("common.fields.color") },
192
- font: { type: "font", label: t("common.fields.font") },
193
- links: { type: "menu", label: t("common.fields.menu") },
194
192
  spacing: { type: "spacing", label: t("common.fields.spacing") },
195
193
 
196
194
  // Dynamic post lists. Use this only on page sections that intentionally
@@ -369,6 +367,12 @@ platform. In the section render function, call
369
367
  with the exact posts field key. Never import Prisma, call platform APIs, or
370
368
  query the database from theme code.
371
369
 
370
+ When rendering posts returned by `getPostResource`, build links from the
371
+ platform-provided `post.url` first. If it is missing, derive the URL only from
372
+ `post.slug` as `/posts/${encodeURIComponent(post.slug)}`; if neither exists,
373
+ use `#`. Do not guess alternate fields such as `href`, `path`, `permalink`,
374
+ `postUrl`, or `canonicalUrl`.
375
+
372
376
  Do not add `resourceQuery: { type: "posts" }` or
373
377
  `resource_query: { type: "posts" }`. Do not assume the field must be named
374
378
  `query`. A section may have only one top-level posts field; do not nest posts
@@ -492,11 +496,11 @@ radius, shadows, or spacing.
492
496
  - Section props may expose semantic choices such as `tone`, `variant`,
493
497
  `columns`, `mediaPosition`, `showImage`, or `spacing`. Map those choices to
494
498
  the existing design tokens and shared CSS classes.
495
- - Do not add raw `color`, `font`, `spacing`, `radius`, or `shadow` fields to a
499
+ - Do not add raw `color`, typography, `spacing`, `radius`, or `shadow` fields to a
496
500
  section just because the CSS has a value. Expose a design token field only
497
501
  when the user should intentionally customize that value per component
498
502
  instance. Otherwise, keep the value in the theme CSS.
499
- - Use `color`, `font`, and `spacing` field types only for real editor-facing
503
+ - Use `color` and `spacing` field types only for real editor-facing
500
504
  design controls. Use `select`/`radio` for named variants that are already
501
505
  part of the theme design system.
502
506
  - Local blocks inside `blockSlots` inherit the host section's design system.
@@ -534,10 +538,11 @@ Use the most specific field type available. A generic `text` field may pass type
534
538
 
535
539
  - Always use `url` for links and routes, including anchors, `mailto:` links, and external URLs. Do not use `text` for href-like props.
536
540
  - Use `image` for images, `video` for videos, and `media` only when the same prop intentionally accepts mixed media.
537
- - Use `color` for color values, `icon` for icon names, `font` for font selections, `range` for bounded numbers, `spacing` for spacing tokens, and `menu` for navigation items.
541
+ - Use `color` for color values, `icon` for icon names, `range` for bounded numbers, and `spacing` for spacing tokens.
542
+ - Use `select` for typography choices and `array`/`object` fields for navigation lists.
538
543
  - Use `select` or `radio` for fixed choices. Keep option values stable, short, and serializable.
539
544
  - Use `array` for repeatable items and `object` for grouped settings. Keep nested field names aligned with the prop shape and `defaultProps`.
540
- - Use `textarea` for multi-sentence copy. Use `text` only for short labels, headings, slugs, names, or plain strings that are not URLs, media, colors, icons, fonts, or menus.
545
+ - Use `textarea` for multi-sentence copy. Use `text` only for short labels, headings, slugs, names, or plain strings that are not URLs, media, colors, icons, typography choices, or navigation lists.
541
546
  - Use `t(...)` for every editor-facing `label` in components, fields, nested
542
547
  `arrayFields` / `object.fields`, local blocks, and option lists. Add matching
543
548
  keys to `src/locales/en.json` at the same time.
@@ -589,7 +594,7 @@ Good component instructions explain:
589
594
  - Frequency: whether it should appear once, multiple times, or only near another section.
590
595
  - Composition: required neighboring content or local blocks, when relevant.
591
596
 
592
- - For icons, expose props with `{ type: "icon" }`, type values as `SudaLucideIconName`, render them with `SudaLucideIcon` from `@sudajs/theme-engine/runtime`, and store canonical Lucide names such as `"rocket"` or `"mouse-pointer-click"` (not `"lucide-rocket"`). Do not keep theme-local icon maps, emoji/icon switch statements, or custom SVG icon registries unless the theme truly needs a bespoke non-Lucide graphic.
597
+ - For icons, expose props with `{ type: "icon" }`, type values as `SudaLucideIconName`, render them with `SudaLucideIcon` from `@sudajs/theme-engine/icons`, and store canonical Lucide names such as `"rocket"` or `"mouse-pointer-click"` (not `"lucide-rocket"`). Do not keep theme-local icon maps, emoji/icon switch statements, or custom SVG icon registries unless the theme truly needs a bespoke non-Lucide graphic.
593
598
  - Add optional field-level `ai.instructions`, `ai.required`, or `ai.exclude` when a prop needs generation guidance beyond its label and type.
594
599
  - Use `ai.exclude: true` only for structural or editor-only components, and still provide instructions explaining why AI must not generate them. `PageOutlet` is the standard example.
595
600
 
@@ -1,8 +1,11 @@
1
- import type { SudaComponentConfig, SudaLucideIconName } from "@sudajs/theme-engine";
1
+ import type { SudaComponentConfig } from "@sudajs/theme-engine";
2
+ import {
3
+ SudaLucideIcon,
4
+ type SudaLucideIconName,
5
+ } from "@sudajs/theme-engine/icons";
2
6
  import {
3
7
  getPostResource,
4
8
  resolveAsset,
5
- SudaLucideIcon,
6
9
  type ThemePostResourceQuery,
7
10
  type ThemeRenderMetadata,
8
11
  } from "@sudajs/theme-engine/runtime";
@@ -245,6 +248,8 @@ export const FeaturedPosts: SudaComponentConfig<FeaturedPostsProps> = {
245
248
  fieldKey: "postList",
246
249
  });
247
250
  const posts = resource.posts;
251
+ const postHref = (post: (typeof posts)[number]) =>
252
+ post.url || (post.slug ? `/posts/${encodeURIComponent(post.slug)}` : "#");
248
253
  return (
249
254
  <section className="__SUDA_THEME_KEY__-section">
250
255
  <h2>{title}</h2>
@@ -258,7 +263,7 @@ export const FeaturedPosts: SudaComponentConfig<FeaturedPostsProps> = {
258
263
  </p>
259
264
  <h3>{post.title}</h3>
260
265
  <p>{post.excerpt}</p>
261
- <a href={post.url}>{post.title}</a>
266
+ <a href={postHref(post)}>{post.title}</a>
262
267
  </article>
263
268
  ))
264
269
  ) : (