@brunoalz/smartgesti-site-editor 1.4.2 → 1.5.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/dist/editor/BlockSelector.js +4 -2
- package/dist/editor/BlockSelector.js.map +1 -1
- package/dist/engine/export/exporters/layout/GridExporter.d.ts.map +1 -1
- package/dist/engine/export/exporters/layout/GridExporter.js +29 -12
- package/dist/engine/export/exporters/layout/GridExporter.js.map +1 -1
- package/dist/engine/export/exporters/sections/BlogPostExporters.d.ts +2 -0
- package/dist/engine/export/exporters/sections/BlogPostExporters.d.ts.map +1 -1
- package/dist/engine/export/exporters/sections/BlogPostExporters.js +183 -119
- package/dist/engine/export/exporters/sections/BlogPostExporters.js.map +1 -1
- package/dist/engine/export/exporters/sections/index.d.ts.map +1 -1
- package/dist/engine/export/exporters/sections/index.js +26 -24
- package/dist/engine/export/exporters/sections/index.js.map +1 -1
- package/dist/engine/index.js +97 -95
- package/dist/engine/index.js.map +1 -1
- package/dist/engine/plugins/builtin/blog/manifest.d.ts.map +1 -1
- package/dist/engine/plugins/builtin/blog/manifest.js +160 -72
- package/dist/engine/plugins/builtin/blog/manifest.js.map +1 -1
- package/dist/engine/plugins/contentHydration.js +144 -68
- package/dist/engine/plugins/contentHydration.js.map +1 -1
- package/dist/engine/registry/blocks/layout/grid.d.ts.map +1 -1
- package/dist/engine/registry/blocks/layout/grid.js +10 -4
- package/dist/engine/registry/blocks/layout/grid.js.map +1 -1
- package/dist/engine/registry/blocks/sections/blogRecentPosts.d.ts +3 -0
- package/dist/engine/registry/blocks/sections/blogRecentPosts.d.ts.map +1 -0
- package/dist/engine/registry/blocks/sections/blogRecentPosts.js +29 -0
- package/dist/engine/registry/blocks/sections/blogRecentPosts.js.map +1 -0
- package/dist/engine/registry/blocks/sections/blogTagCloud.d.ts +3 -0
- package/dist/engine/registry/blocks/sections/blogTagCloud.d.ts.map +1 -0
- package/dist/engine/registry/blocks/sections/blogTagCloud.js +31 -0
- package/dist/engine/registry/blocks/sections/blogTagCloud.js.map +1 -0
- package/dist/engine/registry/blocks/sections/index.d.ts +2 -0
- package/dist/engine/registry/blocks/sections/index.d.ts.map +1 -1
- package/dist/engine/render/renderers/layout/GridRenderer.d.ts.map +1 -1
- package/dist/engine/render/renderers/layout/GridRenderer.js +21 -18
- package/dist/engine/render/renderers/layout/GridRenderer.js.map +1 -1
- package/dist/engine/render/renderers/sections/BlogPostDetailRenderer.d.ts.map +1 -1
- package/dist/engine/render/renderers/sections/BlogPostDetailRenderer.js +66 -47
- package/dist/engine/render/renderers/sections/BlogPostDetailRenderer.js.map +1 -1
- package/dist/engine/render/renderers/sections/BlogPostGridRenderer.d.ts.map +1 -1
- package/dist/engine/render/renderers/sections/BlogPostGridRenderer.js +175 -32
- package/dist/engine/render/renderers/sections/BlogPostGridRenderer.js.map +1 -1
- package/dist/engine/render/renderers/sections/BlogRecentPostsRenderer.d.ts +3 -0
- package/dist/engine/render/renderers/sections/BlogRecentPostsRenderer.d.ts.map +1 -0
- package/dist/engine/render/renderers/sections/BlogRecentPostsRenderer.js +148 -0
- package/dist/engine/render/renderers/sections/BlogRecentPostsRenderer.js.map +1 -0
- package/dist/engine/render/renderers/sections/BlogTagCloudRenderer.d.ts +3 -0
- package/dist/engine/render/renderers/sections/BlogTagCloudRenderer.d.ts.map +1 -0
- package/dist/engine/render/renderers/sections/BlogTagCloudRenderer.js +134 -0
- package/dist/engine/render/renderers/sections/BlogTagCloudRenderer.js.map +1 -0
- package/dist/engine/render/renderers/sections/index.js +20 -16
- package/dist/engine/render/renderers/sections/index.js.map +1 -1
- package/dist/engine/schema/siteDocument.d.ts +57 -2
- package/dist/engine/schema/siteDocument.d.ts.map +1 -1
- package/dist/engine/schema/siteDocument.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +108 -106
- package/dist/index.js.map +1 -1
- package/dist/viewer/LandingPageViewer.js +11 -11
- package/dist/viewer/LandingPageViewer.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,47 +1,60 @@
|
|
|
1
|
-
import { logger as
|
|
2
|
-
async function
|
|
1
|
+
import { logger as f } from "../../utils/logger.js";
|
|
2
|
+
async function R(t, n, r, e) {
|
|
3
3
|
if (!t.dataSource)
|
|
4
4
|
return t;
|
|
5
|
-
const { provider:
|
|
6
|
-
if (!
|
|
7
|
-
return
|
|
8
|
-
`ContentProvider "${
|
|
5
|
+
const { provider: a, mode: s, paramMapping: c } = t.dataSource, d = n.get(a);
|
|
6
|
+
if (!d)
|
|
7
|
+
return f.warn(
|
|
8
|
+
`ContentProvider "${a}" not found for page "${t.id}". Rendering with static props.`
|
|
9
9
|
), t;
|
|
10
10
|
try {
|
|
11
|
-
if (
|
|
12
|
-
return await
|
|
13
|
-
if (
|
|
14
|
-
const
|
|
15
|
-
return
|
|
11
|
+
if (s === "list")
|
|
12
|
+
return await C(t, d, e);
|
|
13
|
+
if (s === "single") {
|
|
14
|
+
const p = $(c, r);
|
|
15
|
+
return p ? await I(t, d, p) : (f.warn(
|
|
16
16
|
`Could not resolve ID/slug for page "${t.id}" from URL params. Using static props.`
|
|
17
17
|
), t);
|
|
18
18
|
}
|
|
19
19
|
return t;
|
|
20
|
-
} catch (
|
|
21
|
-
return
|
|
20
|
+
} catch (p) {
|
|
21
|
+
return f.error(`Error hydrating page "${t.id}":`, p), t;
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
|
-
|
|
25
|
-
const
|
|
24
|
+
function v(t, n) {
|
|
25
|
+
const e = `/site/p/${t.slug && t.slug !== "home" ? t.slug : "blog"}`, a = new URLSearchParams(), s = n?.filter;
|
|
26
|
+
return s?.search && a.set("busca", s.search), s?.category && a.set("categoria", s.category), a.toString() ? `${e}?${a.toString()}` : e;
|
|
27
|
+
}
|
|
28
|
+
async function C(t, n, r) {
|
|
29
|
+
const e = {
|
|
26
30
|
limit: 12,
|
|
27
31
|
...t.dataSource?.defaultParams,
|
|
28
|
-
...
|
|
29
|
-
},
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
...r
|
|
33
|
+
}, a = await n.fetchList(e), s = (a.items || []).map((i) => n.toBlockProps(i)), c = !!t.dataSource?.defaultParams?._noPagination, d = Math.ceil((a.total || 0) / (a.limit || e.limit || 12)), p = !c && d > 1 ? {
|
|
34
|
+
currentPage: a.page || 1,
|
|
35
|
+
totalPages: d,
|
|
36
|
+
paginationBaseUrl: v(t, r)
|
|
37
|
+
} : void 0, m = t.structure.map((i) => {
|
|
38
|
+
let l = P(i, s, p);
|
|
39
|
+
return l = h(l, s), l;
|
|
32
40
|
});
|
|
33
41
|
return {
|
|
34
42
|
...t,
|
|
35
|
-
structure:
|
|
43
|
+
structure: m
|
|
36
44
|
};
|
|
37
45
|
}
|
|
38
|
-
function
|
|
46
|
+
function P(t, n, r) {
|
|
39
47
|
if (t.type === "blogPostGrid")
|
|
40
48
|
return {
|
|
41
49
|
...t,
|
|
42
50
|
props: {
|
|
43
51
|
...t.props,
|
|
44
|
-
cards: n
|
|
52
|
+
cards: n,
|
|
53
|
+
...r ? {
|
|
54
|
+
currentPage: r.currentPage,
|
|
55
|
+
totalPages: r.totalPages,
|
|
56
|
+
paginationBaseUrl: r.paginationBaseUrl
|
|
57
|
+
} : {}
|
|
45
58
|
}
|
|
46
59
|
};
|
|
47
60
|
const e = t.props;
|
|
@@ -50,25 +63,48 @@ function d(t, n) {
|
|
|
50
63
|
props: {
|
|
51
64
|
...e,
|
|
52
65
|
children: e.children.map(
|
|
53
|
-
(
|
|
66
|
+
(a) => P(a, n, r)
|
|
54
67
|
)
|
|
55
68
|
}
|
|
56
69
|
} : t;
|
|
57
70
|
}
|
|
58
|
-
async function
|
|
59
|
-
const
|
|
60
|
-
if (!
|
|
61
|
-
return
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
71
|
+
async function I(t, n, r) {
|
|
72
|
+
const e = await n.fetchById(r);
|
|
73
|
+
if (!e)
|
|
74
|
+
return f.warn(`Content item "${r}" not found. Using static props.`), t;
|
|
75
|
+
const a = n.toBlockProps(e);
|
|
76
|
+
let s = [], c = [], d = [];
|
|
77
|
+
try {
|
|
78
|
+
const l = (await n.fetchList({ limit: 10, sort: "published_at" })).items || [];
|
|
79
|
+
d = l.map((o) => n.toBlockProps(o)), s = l.filter((o) => o.slug !== r && o.slug).slice(0, 5).map((o) => {
|
|
80
|
+
const u = o.data;
|
|
81
|
+
return {
|
|
82
|
+
title: u.title ?? "",
|
|
83
|
+
slug: o.slug,
|
|
84
|
+
date: o.metadata?.publishedAt ? new Date(o.metadata.publishedAt).toLocaleDateString("pt-BR", { day: "2-digit", month: "short", year: "numeric" }) : void 0,
|
|
85
|
+
image: u.featuredImage ?? void 0,
|
|
86
|
+
category: u.category ?? void 0
|
|
87
|
+
};
|
|
88
|
+
});
|
|
89
|
+
const g = /* @__PURE__ */ new Map();
|
|
90
|
+
for (const o of l) {
|
|
91
|
+
const u = o.data.tags;
|
|
92
|
+
if (u)
|
|
93
|
+
for (const y of u)
|
|
94
|
+
g.set(y, (g.get(y) ?? 0) + 1);
|
|
95
|
+
}
|
|
96
|
+
c = Array.from(g.entries()).map(([o, u]) => ({ name: o, count: u })).sort((o, u) => u.count - o.count);
|
|
97
|
+
} catch (i) {
|
|
98
|
+
f.warn(`Failed to fetch sidebar data for page "${t.id}":`, i);
|
|
99
|
+
}
|
|
100
|
+
const p = t.structure.map((i) => w(i, a, e)).map((i) => A(i, s)).map((i) => B(i, c)).map((i) => h(i, d)), m = S(e, a);
|
|
65
101
|
return {
|
|
66
102
|
...t,
|
|
67
|
-
structure:
|
|
68
|
-
...
|
|
103
|
+
structure: p,
|
|
104
|
+
...m ? { seo: m } : {}
|
|
69
105
|
};
|
|
70
106
|
}
|
|
71
|
-
function
|
|
107
|
+
function w(t, n, r) {
|
|
72
108
|
if (t.type === "blogPostDetail")
|
|
73
109
|
return {
|
|
74
110
|
...t,
|
|
@@ -76,8 +112,8 @@ function p(t, n, e) {
|
|
|
76
112
|
...t.props,
|
|
77
113
|
...n,
|
|
78
114
|
// Preserve metadata
|
|
79
|
-
_contentItemId:
|
|
80
|
-
_contentItemSlug:
|
|
115
|
+
_contentItemId: r.id,
|
|
116
|
+
_contentItemSlug: r.slug
|
|
81
117
|
}
|
|
82
118
|
};
|
|
83
119
|
if (t.type === "blogPostCard")
|
|
@@ -88,74 +124,114 @@ function p(t, n, e) {
|
|
|
88
124
|
...n
|
|
89
125
|
}
|
|
90
126
|
};
|
|
127
|
+
const e = t.props;
|
|
128
|
+
return e.children && Array.isArray(e.children) ? {
|
|
129
|
+
...t,
|
|
130
|
+
props: {
|
|
131
|
+
...e,
|
|
132
|
+
children: e.children.map(
|
|
133
|
+
(a) => w(a, n, r)
|
|
134
|
+
)
|
|
135
|
+
}
|
|
136
|
+
} : t;
|
|
137
|
+
}
|
|
138
|
+
function S(t, n) {
|
|
139
|
+
const r = t.metadata?.seo, e = r?.metaTitle || n.metaTitle || n.title, a = r?.metaDescription || n.metaDescription || n.excerpt, s = r?.ogImage || n.ogImage || n.featuredImage;
|
|
140
|
+
if (!(!e && !a && !s))
|
|
141
|
+
return {
|
|
142
|
+
metaTitle: e,
|
|
143
|
+
metaDescription: a,
|
|
144
|
+
ogImage: s,
|
|
145
|
+
ogType: "article"
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
function A(t, n) {
|
|
149
|
+
if (t.type === "blogRecentPosts")
|
|
150
|
+
return {
|
|
151
|
+
...t,
|
|
152
|
+
props: {
|
|
153
|
+
...t.props,
|
|
154
|
+
posts: n
|
|
155
|
+
}
|
|
156
|
+
};
|
|
91
157
|
const r = t.props;
|
|
92
158
|
return r.children && Array.isArray(r.children) ? {
|
|
93
159
|
...t,
|
|
94
160
|
props: {
|
|
95
161
|
...r,
|
|
96
162
|
children: r.children.map(
|
|
97
|
-
(
|
|
163
|
+
(e) => A(e, n)
|
|
98
164
|
)
|
|
99
165
|
}
|
|
100
166
|
} : t;
|
|
101
167
|
}
|
|
102
|
-
function
|
|
103
|
-
|
|
104
|
-
if (!(!r && !o && !i))
|
|
168
|
+
function B(t, n) {
|
|
169
|
+
if (t.type === "blogTagCloud")
|
|
105
170
|
return {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
171
|
+
...t,
|
|
172
|
+
props: {
|
|
173
|
+
...t.props,
|
|
174
|
+
tags: n
|
|
175
|
+
}
|
|
110
176
|
};
|
|
177
|
+
const r = t.props;
|
|
178
|
+
return r.children && Array.isArray(r.children) ? {
|
|
179
|
+
...t,
|
|
180
|
+
props: {
|
|
181
|
+
...r,
|
|
182
|
+
children: r.children.map(
|
|
183
|
+
(e) => B(e, n)
|
|
184
|
+
)
|
|
185
|
+
}
|
|
186
|
+
} : t;
|
|
111
187
|
}
|
|
112
|
-
function
|
|
188
|
+
function h(t, n) {
|
|
113
189
|
if (t.type === "blogCategoryFilter") {
|
|
114
|
-
const
|
|
115
|
-
for (const
|
|
116
|
-
const
|
|
117
|
-
|
|
190
|
+
const e = /* @__PURE__ */ new Map();
|
|
191
|
+
for (const s of n) {
|
|
192
|
+
const c = s.category;
|
|
193
|
+
c && e.set(c, (e.get(c) || 0) + 1);
|
|
118
194
|
}
|
|
119
|
-
const
|
|
120
|
-
name:
|
|
121
|
-
slug:
|
|
122
|
-
count:
|
|
195
|
+
const a = Array.from(e.entries()).map(([s, c]) => ({
|
|
196
|
+
name: s,
|
|
197
|
+
slug: s,
|
|
198
|
+
count: c
|
|
123
199
|
}));
|
|
124
200
|
return {
|
|
125
201
|
...t,
|
|
126
202
|
props: {
|
|
127
203
|
...t.props,
|
|
128
|
-
categories:
|
|
204
|
+
categories: a
|
|
129
205
|
}
|
|
130
206
|
};
|
|
131
207
|
}
|
|
132
|
-
const
|
|
133
|
-
return
|
|
208
|
+
const r = t.props;
|
|
209
|
+
return r.children && Array.isArray(r.children) ? {
|
|
134
210
|
...t,
|
|
135
211
|
props: {
|
|
136
|
-
...
|
|
137
|
-
children:
|
|
138
|
-
(
|
|
212
|
+
...r,
|
|
213
|
+
children: r.children.map(
|
|
214
|
+
(e) => h(e, n)
|
|
139
215
|
)
|
|
140
216
|
}
|
|
141
217
|
} : t;
|
|
142
218
|
}
|
|
143
|
-
function
|
|
219
|
+
function $(t, n) {
|
|
144
220
|
if (!(!t || !n)) {
|
|
145
|
-
for (const
|
|
146
|
-
const
|
|
147
|
-
if (
|
|
148
|
-
const
|
|
149
|
-
if (
|
|
221
|
+
for (const r of ["slug", "id"]) {
|
|
222
|
+
const e = t[r];
|
|
223
|
+
if (e) {
|
|
224
|
+
const a = e.startsWith(":") ? e.slice(1) : e, s = n[a];
|
|
225
|
+
if (s) return s;
|
|
150
226
|
}
|
|
151
227
|
}
|
|
152
|
-
for (const
|
|
153
|
-
const
|
|
154
|
-
if (
|
|
228
|
+
for (const r of Object.values(t)) {
|
|
229
|
+
const e = r.startsWith(":") ? r.slice(1) : r, a = n[e];
|
|
230
|
+
if (a) return a;
|
|
155
231
|
}
|
|
156
232
|
}
|
|
157
233
|
}
|
|
158
234
|
export {
|
|
159
|
-
|
|
235
|
+
R as hydratePageWithContent
|
|
160
236
|
};
|
|
161
237
|
//# sourceMappingURL=contentHydration.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contentHydration.js","sources":["../../../src/engine/plugins/contentHydration.ts"],"sourcesContent":["/**\n * Content Hydration\n * Hydrates page blocks with data from ContentProviders before rendering.\n *\n * This works at the data level, before either rendering pipeline\n * (React renderers or HTML exporters) processes the blocks.\n */\n\nimport { logger } from \"../../utils/logger\";\nimport type { SitePage, Block, PageSeoConfig } from \"../schema/siteDocument\";\nimport type { ContentProvider, ContentItem, ContentListParams } from \"./types\";\n\n/**\n * Map of provider type → ContentProvider instance\n */\nexport type ContentProviderMap = Map<string, ContentProvider>;\n\n/**\n * Hydrates a page's blocks with data from ContentProviders.\n *\n * For pages with a dataSource:\n * - mode \"list\": fetches list and populates grid blocks' `cards` prop\n * - mode \"single\": fetches single item and spreads props onto detail blocks\n *\n * Returns a new page with hydrated block props (original page is not mutated).\n */\nexport async function hydratePageWithContent(\n page: SitePage,\n providers: ContentProviderMap,\n urlParams?: Record<string, string>,\n fetchParams?: ContentListParams,\n): Promise<SitePage> {\n // No dataSource → return page as-is\n if (!page.dataSource) {\n return page;\n }\n\n const { provider: providerType, mode, paramMapping } = page.dataSource;\n const provider = providers.get(providerType);\n\n if (!provider) {\n logger.warn(\n `ContentProvider \"${providerType}\" not found for page \"${page.id}\". Rendering with static props.`,\n );\n return page;\n }\n\n try {\n if (mode === \"list\") {\n return await hydrateListPage(page, provider, fetchParams);\n }\n\n if (mode === \"single\") {\n // Resolve the ID/slug from URL params\n const idOrSlug = resolveIdFromParams(paramMapping, urlParams);\n if (!idOrSlug) {\n logger.warn(\n `Could not resolve ID/slug for page \"${page.id}\" from URL params. Using static props.`,\n );\n return page;\n }\n return await hydrateSinglePage(page, provider, idOrSlug);\n }\n\n return page;\n } catch (error) {\n logger.error(`Error hydrating page \"${page.id}\":`, error);\n return page;\n }\n}\n\n/**\n * Hydrates a list-mode page: fetches items and populates grid blocks.\n */\nasync function hydrateListPage(\n page: SitePage,\n provider: ContentProvider,\n fetchParams?: ContentListParams,\n): Promise<SitePage> {\n const params: ContentListParams = {\n limit: 12,\n ...page.dataSource?.defaultParams,\n ...fetchParams,\n };\n\n const result = await provider.fetchList(params);\n\n // Convert items to block props (empty array if no results — shows empty state, never mock data)\n const cardProps = (result.items || []).map((item) => provider.toBlockProps(item));\n\n // Hydrate all grid blocks and category filters on the page\n const hydratedStructure = page.structure.map((block) => {\n let hydrated = hydrateGridBlock(block, cardProps);\n hydrated = hydrateCategoryFilterBlock(hydrated, cardProps);\n return hydrated;\n });\n\n return {\n ...page,\n structure: hydratedStructure,\n };\n}\n\n/**\n * Hydrates grid blocks (blogPostGrid, etc.) with card data.\n */\nfunction hydrateGridBlock(\n block: Block,\n cardProps: Record<string, unknown>[],\n): Block {\n // Direct match: blogPostGrid gets cards populated\n if (block.type === \"blogPostGrid\") {\n return {\n ...block,\n props: {\n ...block.props,\n cards: cardProps,\n },\n };\n }\n\n // Recurse into children for nested structures\n const props = block.props as Record<string, unknown>;\n if (props.children && Array.isArray(props.children)) {\n return {\n ...block,\n props: {\n ...props,\n children: (props.children as Block[]).map((child) =>\n hydrateGridBlock(child, cardProps),\n ),\n },\n };\n }\n\n return block;\n}\n\n/**\n * Hydrates a single-mode page: fetches one item and populates detail blocks.\n */\nasync function hydrateSinglePage(\n page: SitePage,\n provider: ContentProvider,\n idOrSlug: string,\n): Promise<SitePage> {\n const item = await provider.fetchById(idOrSlug);\n\n if (!item) {\n logger.warn(`Content item \"${idOrSlug}\" not found. Using static props.`);\n return page;\n }\n\n const blockProps = provider.toBlockProps(item);\n\n // Hydrate all detail blocks on the page\n const hydratedStructure = page.structure.map((block) =>\n hydrateDetailBlock(block, blockProps, item),\n );\n\n // Extract SEO from content item and set on page\n const seo = extractSeoFromContent(item, blockProps);\n\n return {\n ...page,\n structure: hydratedStructure,\n ...(seo ? { seo } : {}),\n };\n}\n\n/**\n * Hydrates detail blocks (blogPostDetail, etc.) with item data.\n */\nfunction hydrateDetailBlock(\n block: Block,\n blockProps: Record<string, unknown>,\n item: ContentItem,\n): Block {\n if (block.type === \"blogPostDetail\") {\n return {\n ...block,\n props: {\n ...block.props,\n ...blockProps,\n // Preserve metadata\n _contentItemId: item.id,\n _contentItemSlug: item.slug,\n },\n };\n }\n\n // Also hydrate blogPostCard blocks that reference the same item\n if (block.type === \"blogPostCard\") {\n return {\n ...block,\n props: {\n ...block.props,\n ...blockProps,\n },\n };\n }\n\n // Recurse into children\n const props = block.props as Record<string, unknown>;\n if (props.children && Array.isArray(props.children)) {\n return {\n ...block,\n props: {\n ...props,\n children: (props.children as Block[]).map((child) =>\n hydrateDetailBlock(child, blockProps, item),\n ),\n },\n };\n }\n\n return block;\n}\n\n/**\n * Extracts SEO configuration from a ContentItem and block props.\n * Priority: item.metadata.seo > blockProps (metaTitle/title, metaDescription/excerpt, ogImage/featuredImage)\n */\nfunction extractSeoFromContent(\n item: ContentItem,\n blockProps: Record<string, unknown>,\n): PageSeoConfig | undefined {\n const seoMeta = item.metadata?.seo;\n\n const metaTitle = seoMeta?.metaTitle || (blockProps.metaTitle as string) || (blockProps.title as string);\n const metaDescription = seoMeta?.metaDescription || (blockProps.metaDescription as string) || (blockProps.excerpt as string);\n const ogImage = seoMeta?.ogImage || (blockProps.ogImage as string) || (blockProps.featuredImage as string);\n\n if (!metaTitle && !metaDescription && !ogImage) {\n return undefined;\n }\n\n return {\n metaTitle,\n metaDescription,\n ogImage,\n ogType: \"article\",\n };\n}\n\n/**\n * Hydrates blogCategoryFilter blocks with category data extracted from posts.\n */\nfunction hydrateCategoryFilterBlock(\n block: Block,\n cardProps: Record<string, unknown>[],\n): Block {\n if (block.type === \"blogCategoryFilter\") {\n // Extract unique categories from posts with counts\n const categoryMap = new Map<string, number>();\n for (const card of cardProps) {\n const cat = card.category as string;\n if (cat) {\n categoryMap.set(cat, (categoryMap.get(cat) || 0) + 1);\n }\n }\n\n const categories = Array.from(categoryMap.entries()).map(([name, count]) => ({\n name,\n slug: name,\n count,\n }));\n\n return {\n ...block,\n props: {\n ...block.props,\n categories,\n },\n };\n }\n\n // Recurse into children\n const props = block.props as Record<string, unknown>;\n if (props.children && Array.isArray(props.children)) {\n return {\n ...block,\n props: {\n ...props,\n children: (props.children as Block[]).map((child) =>\n hydrateCategoryFilterBlock(child, cardProps),\n ),\n },\n };\n }\n\n return block;\n}\n\n/**\n * Resolves the item ID/slug from URL params using paramMapping.\n * e.g., paramMapping: { slug: \":slug\" }, urlParams: { slug: \"my-post\" } → \"my-post\"\n */\nfunction resolveIdFromParams(\n paramMapping?: Record<string, string>,\n urlParams?: Record<string, string>,\n): string | undefined {\n if (!paramMapping || !urlParams) return undefined;\n\n // Try slug first, then id\n for (const key of [\"slug\", \"id\"]) {\n const paramPattern = paramMapping[key];\n if (paramPattern) {\n // Extract param name from pattern (e.g., \":slug\" → \"slug\")\n const paramName = paramPattern.startsWith(\":\")\n ? paramPattern.slice(1)\n : paramPattern;\n const value = urlParams[paramName];\n if (value) return value;\n }\n }\n\n // Fallback: return first available param value\n for (const paramPattern of Object.values(paramMapping)) {\n const paramName = paramPattern.startsWith(\":\")\n ? paramPattern.slice(1)\n : paramPattern;\n const value = urlParams[paramName];\n if (value) return value;\n }\n\n return undefined;\n}\n"],"names":["hydratePageWithContent","page","providers","urlParams","fetchParams","providerType","mode","paramMapping","provider","logger","hydrateListPage","idOrSlug","resolveIdFromParams","hydrateSinglePage","error","params","cardProps","item","hydratedStructure","block","hydrated","hydrateGridBlock","hydrateCategoryFilterBlock","props","child","blockProps","hydrateDetailBlock","seo","extractSeoFromContent","seoMeta","metaTitle","metaDescription","ogImage","categoryMap","card","cat","categories","name","count","key","paramPattern","paramName","value"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"contentHydration.js","sources":["../../../src/engine/plugins/contentHydration.ts"],"sourcesContent":["/**\n * Content Hydration\n * Hydrates page blocks with data from ContentProviders before rendering.\n *\n * This works at the data level, before either rendering pipeline\n * (React renderers or HTML exporters) processes the blocks.\n */\n\nimport { logger } from \"../../utils/logger\";\nimport type { SitePage, Block, PageSeoConfig } from \"../schema/siteDocument\";\nimport type { ContentProvider, ContentItem, ContentListParams } from \"./types\";\n\n/**\n * Map of provider type → ContentProvider instance\n */\nexport type ContentProviderMap = Map<string, ContentProvider>;\n\n/**\n * Hydrates a page's blocks with data from ContentProviders.\n *\n * For pages with a dataSource:\n * - mode \"list\": fetches list and populates grid blocks' `cards` prop\n * - mode \"single\": fetches single item and spreads props onto detail blocks\n *\n * Returns a new page with hydrated block props (original page is not mutated).\n */\nexport async function hydratePageWithContent(\n page: SitePage,\n providers: ContentProviderMap,\n urlParams?: Record<string, string>,\n fetchParams?: ContentListParams,\n): Promise<SitePage> {\n // No dataSource → return page as-is\n if (!page.dataSource) {\n return page;\n }\n\n const { provider: providerType, mode, paramMapping } = page.dataSource;\n const provider = providers.get(providerType);\n\n if (!provider) {\n logger.warn(\n `ContentProvider \"${providerType}\" not found for page \"${page.id}\". Rendering with static props.`,\n );\n return page;\n }\n\n try {\n if (mode === \"list\") {\n return await hydrateListPage(page, provider, fetchParams);\n }\n\n if (mode === \"single\") {\n // Resolve the ID/slug from URL params\n const idOrSlug = resolveIdFromParams(paramMapping, urlParams);\n if (!idOrSlug) {\n logger.warn(\n `Could not resolve ID/slug for page \"${page.id}\" from URL params. Using static props.`,\n );\n return page;\n }\n return await hydrateSinglePage(page, provider, idOrSlug);\n }\n\n return page;\n } catch (error) {\n logger.error(`Error hydrating page \"${page.id}\":`, error);\n return page;\n }\n}\n\n/**\n * Pagination metadata passed from hydration to grid blocks.\n */\ninterface PaginationMeta {\n currentPage: number;\n totalPages: number;\n paginationBaseUrl: string;\n}\n\n/**\n * Builds a pagination base URL from the page slug and current filter params.\n * Preserves search/category so pagination links keep the active filters.\n * Uses /site/p/ prefix to match the consumer route pattern (same as viewAllHref, linkHref).\n */\nfunction buildPaginationBaseUrl(\n page: SitePage,\n fetchParams?: ContentListParams,\n): string {\n // Always paginate on the blog listing page — home page widget points to blog page\n const slug = page.slug && page.slug !== \"home\" ? page.slug : \"blog\";\n const basePath = `/site/p/${slug}`;\n\n const params = new URLSearchParams();\n const filter = fetchParams?.filter as Record<string, string> | undefined;\n if (filter?.search) params.set(\"busca\", filter.search);\n if (filter?.category) params.set(\"categoria\", filter.category);\n\n return params.toString() ? `${basePath}?${params.toString()}` : basePath;\n}\n\n/**\n * Hydrates a list-mode page: fetches items and populates grid blocks.\n */\nasync function hydrateListPage(\n page: SitePage,\n provider: ContentProvider,\n fetchParams?: ContentListParams,\n): Promise<SitePage> {\n const params: ContentListParams = {\n limit: 12,\n ...page.dataSource?.defaultParams,\n ...fetchParams,\n };\n\n const result = await provider.fetchList(params);\n\n // Convert items to block props (empty array if no results — shows empty state, never mock data)\n const cardProps = (result.items || []).map((item) => provider.toBlockProps(item));\n\n // Build pagination metadata (only when there are multiple pages)\n // _noPagination flag suppresses pagination for synthetic dataSource (e.g., home page blog widget)\n const noPagination = !!(page.dataSource?.defaultParams as Record<string, unknown> | undefined)?._noPagination;\n const totalPages = Math.ceil((result.total || 0) / (result.limit || params.limit || 12));\n const pagination: PaginationMeta | undefined = !noPagination && totalPages > 1\n ? {\n currentPage: result.page || 1,\n totalPages,\n paginationBaseUrl: buildPaginationBaseUrl(page, fetchParams),\n }\n : undefined;\n\n // Hydrate all grid blocks and category filters on the page\n const hydratedStructure = page.structure.map((block) => {\n let hydrated = hydrateGridBlock(block, cardProps, pagination);\n hydrated = hydrateCategoryFilterBlock(hydrated, cardProps);\n return hydrated;\n });\n\n return {\n ...page,\n structure: hydratedStructure,\n };\n}\n\n/**\n * Hydrates grid blocks (blogPostGrid, etc.) with card data and pagination.\n */\nfunction hydrateGridBlock(\n block: Block,\n cardProps: Record<string, unknown>[],\n pagination?: PaginationMeta,\n): Block {\n // Direct match: blogPostGrid gets cards + pagination populated\n if (block.type === \"blogPostGrid\") {\n return {\n ...block,\n props: {\n ...block.props,\n cards: cardProps,\n ...(pagination ? {\n currentPage: pagination.currentPage,\n totalPages: pagination.totalPages,\n paginationBaseUrl: pagination.paginationBaseUrl,\n } : {}),\n },\n };\n }\n\n // Recurse into children for nested structures\n const props = block.props as Record<string, unknown>;\n if (props.children && Array.isArray(props.children)) {\n return {\n ...block,\n props: {\n ...props,\n children: (props.children as Block[]).map((child) =>\n hydrateGridBlock(child, cardProps, pagination),\n ),\n },\n };\n }\n\n return block;\n}\n\n/**\n * Hydrates a single-mode page: fetches one item and populates detail blocks.\n * Also fetches sidebar data (recent posts, tags, categories) for widgets.\n */\nasync function hydrateSinglePage(\n page: SitePage,\n provider: ContentProvider,\n idOrSlug: string,\n): Promise<SitePage> {\n const item = await provider.fetchById(idOrSlug);\n\n if (!item) {\n logger.warn(`Content item \"${idOrSlug}\" not found. Using static props.`);\n return page;\n }\n\n const blockProps = provider.toBlockProps(item);\n\n // Fetch recent posts for sidebar widgets\n let recentPosts: Array<{ title: string; slug: string; date?: string; image?: string; category?: string }> = [];\n let tagCloud: Array<{ name: string; count: number }> = [];\n let sidebarCardProps: Record<string, unknown>[] = [];\n\n try {\n const recentResult = await provider.fetchList({ limit: 10, sort: 'published_at' });\n const allItems = recentResult.items || [];\n\n // Map to card props for category filter hydration\n sidebarCardProps = allItems.map((i) => provider.toBlockProps(i));\n\n // Map recent posts (exclude current post)\n recentPosts = allItems\n .filter((i) => i.slug !== idOrSlug && i.slug)\n .slice(0, 5)\n .map((i) => {\n const d = i.data as Record<string, any>;\n return {\n title: (d.title as string) ?? '',\n slug: i.slug as string,\n date: i.metadata?.publishedAt\n ? new Date(i.metadata.publishedAt).toLocaleDateString('pt-BR', { day: '2-digit', month: 'short', year: 'numeric' })\n : undefined,\n image: (d.featuredImage as string) ?? undefined,\n category: (d.category as string) ?? undefined,\n };\n });\n\n // Extract tags from all posts\n const allTags = new Map<string, number>();\n for (const i of allItems) {\n const tags = (i.data as Record<string, any>).tags as string[] | undefined;\n if (tags) {\n for (const tag of tags) {\n allTags.set(tag, (allTags.get(tag) ?? 0) + 1);\n }\n }\n }\n tagCloud = Array.from(allTags.entries())\n .map(([name, count]) => ({ name, count }))\n .sort((a, b) => b.count - a.count);\n } catch (err) {\n logger.warn(`Failed to fetch sidebar data for page \"${page.id}\":`, err);\n }\n\n // Hydrate all blocks on the page\n const hydratedStructure = page.structure\n .map((block) => hydrateDetailBlock(block, blockProps, item))\n .map((block) => hydrateRecentPostsBlock(block, recentPosts))\n .map((block) => hydrateTagCloudBlock(block, tagCloud))\n .map((block) => hydrateCategoryFilterBlock(block, sidebarCardProps));\n\n // Extract SEO from content item and set on page\n const seo = extractSeoFromContent(item, blockProps);\n\n return {\n ...page,\n structure: hydratedStructure,\n ...(seo ? { seo } : {}),\n };\n}\n\n/**\n * Hydrates detail blocks (blogPostDetail, etc.) with item data.\n */\nfunction hydrateDetailBlock(\n block: Block,\n blockProps: Record<string, unknown>,\n item: ContentItem,\n): Block {\n if (block.type === \"blogPostDetail\") {\n return {\n ...block,\n props: {\n ...block.props,\n ...blockProps,\n // Preserve metadata\n _contentItemId: item.id,\n _contentItemSlug: item.slug,\n },\n };\n }\n\n // Also hydrate blogPostCard blocks that reference the same item\n if (block.type === \"blogPostCard\") {\n return {\n ...block,\n props: {\n ...block.props,\n ...blockProps,\n },\n };\n }\n\n // Recurse into children\n const props = block.props as Record<string, unknown>;\n if (props.children && Array.isArray(props.children)) {\n return {\n ...block,\n props: {\n ...props,\n children: (props.children as Block[]).map((child) =>\n hydrateDetailBlock(child, blockProps, item),\n ),\n },\n };\n }\n\n return block;\n}\n\n/**\n * Extracts SEO configuration from a ContentItem and block props.\n * Priority: item.metadata.seo > blockProps (metaTitle/title, metaDescription/excerpt, ogImage/featuredImage)\n */\nfunction extractSeoFromContent(\n item: ContentItem,\n blockProps: Record<string, unknown>,\n): PageSeoConfig | undefined {\n const seoMeta = item.metadata?.seo;\n\n const metaTitle = seoMeta?.metaTitle || (blockProps.metaTitle as string) || (blockProps.title as string);\n const metaDescription = seoMeta?.metaDescription || (blockProps.metaDescription as string) || (blockProps.excerpt as string);\n const ogImage = seoMeta?.ogImage || (blockProps.ogImage as string) || (blockProps.featuredImage as string);\n\n if (!metaTitle && !metaDescription && !ogImage) {\n return undefined;\n }\n\n return {\n metaTitle,\n metaDescription,\n ogImage,\n ogType: \"article\",\n };\n}\n\n/**\n * Hydrates blogRecentPosts blocks with recent post data.\n */\nfunction hydrateRecentPostsBlock(\n block: Block,\n recentPosts: Array<{ title: string; slug: string; date?: string; image?: string; category?: string }>,\n): Block {\n if (block.type === \"blogRecentPosts\") {\n return {\n ...block,\n props: {\n ...block.props,\n posts: recentPosts,\n },\n } as Block;\n }\n\n // Recurse into children\n const props = block.props as Record<string, unknown>;\n if (props.children && Array.isArray(props.children)) {\n return {\n ...block,\n props: {\n ...props,\n children: (props.children as Block[]).map((child) =>\n hydrateRecentPostsBlock(child, recentPosts),\n ),\n },\n } as Block;\n }\n\n return block;\n}\n\n/**\n * Hydrates blogTagCloud blocks with tag data.\n */\nfunction hydrateTagCloudBlock(\n block: Block,\n tags: Array<{ name: string; count: number }>,\n): Block {\n if (block.type === \"blogTagCloud\") {\n return {\n ...block,\n props: {\n ...block.props,\n tags,\n },\n } as Block;\n }\n\n // Recurse into children\n const props = block.props as Record<string, unknown>;\n if (props.children && Array.isArray(props.children)) {\n return {\n ...block,\n props: {\n ...props,\n children: (props.children as Block[]).map((child) =>\n hydrateTagCloudBlock(child, tags),\n ),\n },\n } as Block;\n }\n\n return block;\n}\n\n/**\n * Hydrates blogCategoryFilter blocks with category data extracted from posts.\n */\nfunction hydrateCategoryFilterBlock(\n block: Block,\n cardProps: Record<string, unknown>[],\n): Block {\n if (block.type === \"blogCategoryFilter\") {\n // Extract unique categories from posts with counts\n const categoryMap = new Map<string, number>();\n for (const card of cardProps) {\n const cat = card.category as string;\n if (cat) {\n categoryMap.set(cat, (categoryMap.get(cat) || 0) + 1);\n }\n }\n\n const categories = Array.from(categoryMap.entries()).map(([name, count]) => ({\n name,\n slug: name,\n count,\n }));\n\n return {\n ...block,\n props: {\n ...block.props,\n categories,\n },\n };\n }\n\n // Recurse into children\n const props = block.props as Record<string, unknown>;\n if (props.children && Array.isArray(props.children)) {\n return {\n ...block,\n props: {\n ...props,\n children: (props.children as Block[]).map((child) =>\n hydrateCategoryFilterBlock(child, cardProps),\n ),\n },\n };\n }\n\n return block;\n}\n\n/**\n * Resolves the item ID/slug from URL params using paramMapping.\n * e.g., paramMapping: { slug: \":slug\" }, urlParams: { slug: \"my-post\" } → \"my-post\"\n */\nfunction resolveIdFromParams(\n paramMapping?: Record<string, string>,\n urlParams?: Record<string, string>,\n): string | undefined {\n if (!paramMapping || !urlParams) return undefined;\n\n // Try slug first, then id\n for (const key of [\"slug\", \"id\"]) {\n const paramPattern = paramMapping[key];\n if (paramPattern) {\n // Extract param name from pattern (e.g., \":slug\" → \"slug\")\n const paramName = paramPattern.startsWith(\":\")\n ? paramPattern.slice(1)\n : paramPattern;\n const value = urlParams[paramName];\n if (value) return value;\n }\n }\n\n // Fallback: return first available param value\n for (const paramPattern of Object.values(paramMapping)) {\n const paramName = paramPattern.startsWith(\":\")\n ? paramPattern.slice(1)\n : paramPattern;\n const value = urlParams[paramName];\n if (value) return value;\n }\n\n return undefined;\n}\n"],"names":["hydratePageWithContent","page","providers","urlParams","fetchParams","providerType","mode","paramMapping","provider","logger","hydrateListPage","idOrSlug","resolveIdFromParams","hydrateSinglePage","error","buildPaginationBaseUrl","basePath","params","filter","result","cardProps","item","noPagination","totalPages","pagination","hydratedStructure","block","hydrated","hydrateGridBlock","hydrateCategoryFilterBlock","props","child","blockProps","recentPosts","tagCloud","sidebarCardProps","allItems","i","d","allTags","tags","tag","name","count","a","b","err","hydrateDetailBlock","hydrateRecentPostsBlock","hydrateTagCloudBlock","seo","extractSeoFromContent","seoMeta","metaTitle","metaDescription","ogImage","categoryMap","card","cat","categories","key","paramPattern","paramName","value"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grid.d.ts","sourceRoot":"","sources":["../../../../../src/engine/registry/blocks/layout/grid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG9C,eAAO,MAAM,SAAS,EAAE,
|
|
1
|
+
{"version":3,"file":"grid.d.ts","sourceRoot":"","sources":["../../../../../src/engine/registry/blocks/layout/grid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG9C,eAAO,MAAM,SAAS,EAAE,eA+BvB,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { componentRegistry as
|
|
2
|
-
const
|
|
1
|
+
import { componentRegistry as e } from "../../registry.js";
|
|
2
|
+
const o = {
|
|
3
3
|
type: "grid",
|
|
4
4
|
name: "Grid",
|
|
5
5
|
description: "Layout em grid responsivo",
|
|
@@ -18,6 +18,12 @@ const e = {
|
|
|
18
18
|
max: 12,
|
|
19
19
|
group: "Layout"
|
|
20
20
|
},
|
|
21
|
+
colTemplate: {
|
|
22
|
+
label: "Template de Colunas",
|
|
23
|
+
description: "CSS grid-template-columns (ex: '1fr 320px'). Se definido, sobrescreve 'Colunas'.",
|
|
24
|
+
inputType: "text",
|
|
25
|
+
group: "Layout"
|
|
26
|
+
},
|
|
21
27
|
gap: {
|
|
22
28
|
label: "Gap",
|
|
23
29
|
inputType: "text",
|
|
@@ -25,8 +31,8 @@ const e = {
|
|
|
25
31
|
}
|
|
26
32
|
}
|
|
27
33
|
};
|
|
28
|
-
|
|
34
|
+
e.register(o);
|
|
29
35
|
export {
|
|
30
|
-
|
|
36
|
+
o as gridBlock
|
|
31
37
|
};
|
|
32
38
|
//# sourceMappingURL=grid.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grid.js","sources":["../../../../../src/engine/registry/blocks/layout/grid.ts"],"sourcesContent":["import { BlockDefinition } from \"../../types\";\nimport { componentRegistry } from \"../../registry\";\n\nexport const gridBlock: BlockDefinition = {\n type: \"grid\",\n name: \"Grid\",\n description: \"Layout em grid responsivo\",\n category: \"layout\",\n canHaveChildren: true,\n defaultProps: {\n cols: 3,\n gap: \"1rem\",\n },\n inspectorMeta: {\n cols: {\n label: \"Colunas\",\n description: \"Número de colunas (ou objeto responsivo)\",\n inputType: \"number\",\n min: 1,\n max: 12,\n group: \"Layout\",\n },\n gap: {\n label: \"Gap\",\n inputType: \"text\",\n group: \"Layout\",\n },\n },\n};\n\n// Auto-registro\ncomponentRegistry.register(gridBlock);\n"],"names":["gridBlock","componentRegistry"],"mappings":";AAGO,MAAMA,IAA6B;AAAA,EACxC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,aAAa;AAAA,EACb,UAAU;AAAA,EACV,iBAAiB;AAAA,EACjB,cAAc;AAAA,IACZ,MAAM;AAAA,IACN,KAAK;AAAA,EAAA;AAAA,EAEP,eAAe;AAAA,IACb,MAAM;AAAA,MACJ,OAAO;AAAA,MACP,aAAa;AAAA,MACb,WAAW;AAAA,MACX,KAAK;AAAA,MACL,KAAK;AAAA,MACL,OAAO;AAAA,IAAA;AAAA,IAET,KAAK;AAAA,MACH,OAAO;AAAA,MACP,WAAW;AAAA,MACX,OAAO;AAAA,IAAA;AAAA,EACT;AAEJ;AAGAC,EAAkB,SAASD,CAAS;"}
|
|
1
|
+
{"version":3,"file":"grid.js","sources":["../../../../../src/engine/registry/blocks/layout/grid.ts"],"sourcesContent":["import { BlockDefinition } from \"../../types\";\nimport { componentRegistry } from \"../../registry\";\n\nexport const gridBlock: BlockDefinition = {\n type: \"grid\",\n name: \"Grid\",\n description: \"Layout em grid responsivo\",\n category: \"layout\",\n canHaveChildren: true,\n defaultProps: {\n cols: 3,\n gap: \"1rem\",\n },\n inspectorMeta: {\n cols: {\n label: \"Colunas\",\n description: \"Número de colunas (ou objeto responsivo)\",\n inputType: \"number\",\n min: 1,\n max: 12,\n group: \"Layout\",\n },\n colTemplate: {\n label: \"Template de Colunas\",\n description: \"CSS grid-template-columns (ex: '1fr 320px'). Se definido, sobrescreve 'Colunas'.\",\n inputType: \"text\",\n group: \"Layout\",\n },\n gap: {\n label: \"Gap\",\n inputType: \"text\",\n group: \"Layout\",\n },\n },\n};\n\n// Auto-registro\ncomponentRegistry.register(gridBlock);\n"],"names":["gridBlock","componentRegistry"],"mappings":";AAGO,MAAMA,IAA6B;AAAA,EACxC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,aAAa;AAAA,EACb,UAAU;AAAA,EACV,iBAAiB;AAAA,EACjB,cAAc;AAAA,IACZ,MAAM;AAAA,IACN,KAAK;AAAA,EAAA;AAAA,EAEP,eAAe;AAAA,IACb,MAAM;AAAA,MACJ,OAAO;AAAA,MACP,aAAa;AAAA,MACb,WAAW;AAAA,MACX,KAAK;AAAA,MACL,KAAK;AAAA,MACL,OAAO;AAAA,IAAA;AAAA,IAET,aAAa;AAAA,MACX,OAAO;AAAA,MACP,aAAa;AAAA,MACb,WAAW;AAAA,MACX,OAAO;AAAA,IAAA;AAAA,IAET,KAAK;AAAA,MACH,OAAO;AAAA,MACP,WAAW;AAAA,MACX,OAAO;AAAA,IAAA;AAAA,EACT;AAEJ;AAGAC,EAAkB,SAASD,CAAS;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blogRecentPosts.d.ts","sourceRoot":"","sources":["../../../../../src/engine/registry/blocks/sections/blogRecentPosts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG9C,eAAO,MAAM,oBAAoB,EAAE,eAsBlC,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { componentRegistry as e } from "../../registry.js";
|
|
2
|
+
const t = {
|
|
3
|
+
type: "blogRecentPosts",
|
|
4
|
+
name: "Posts Recentes",
|
|
5
|
+
description: "Widget com os posts mais recentes do blog",
|
|
6
|
+
category: "sections",
|
|
7
|
+
pluginId: "blog",
|
|
8
|
+
defaultProps: {
|
|
9
|
+
title: "Posts Recentes",
|
|
10
|
+
count: 5,
|
|
11
|
+
showThumbnail: !0,
|
|
12
|
+
showDate: !0,
|
|
13
|
+
showCategory: !1,
|
|
14
|
+
posts: []
|
|
15
|
+
},
|
|
16
|
+
inspectorMeta: {
|
|
17
|
+
title: { label: "Título", inputType: "text", group: "Conteúdo" },
|
|
18
|
+
count: { label: "Quantidade", inputType: "number", min: 1, max: 10, group: "Conteúdo" },
|
|
19
|
+
showThumbnail: { label: "Mostrar Miniatura", inputType: "checkbox", group: "Exibição" },
|
|
20
|
+
showDate: { label: "Mostrar Data", inputType: "checkbox", group: "Exibição" },
|
|
21
|
+
showCategory: { label: "Mostrar Categoria", inputType: "checkbox", group: "Exibição" },
|
|
22
|
+
posts: { label: "Posts", inputType: "text", readOnly: !0, group: "Dados" }
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
e.register(t);
|
|
26
|
+
export {
|
|
27
|
+
t as blogRecentPostsBlock
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=blogRecentPosts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blogRecentPosts.js","sources":["../../../../../src/engine/registry/blocks/sections/blogRecentPosts.ts"],"sourcesContent":["import { BlockDefinition } from \"../../types\";\nimport { componentRegistry } from \"../../registry\";\n\nexport const blogRecentPostsBlock: BlockDefinition = {\n type: \"blogRecentPosts\",\n name: \"Posts Recentes\",\n description: \"Widget com os posts mais recentes do blog\",\n category: \"sections\",\n pluginId: \"blog\",\n defaultProps: {\n title: \"Posts Recentes\",\n count: 5,\n showThumbnail: true,\n showDate: true,\n showCategory: false,\n posts: [],\n },\n inspectorMeta: {\n title: { label: \"Título\", inputType: \"text\", group: \"Conteúdo\" },\n count: { label: \"Quantidade\", inputType: \"number\", min: 1, max: 10, group: \"Conteúdo\" },\n showThumbnail: { label: \"Mostrar Miniatura\", inputType: \"checkbox\", group: \"Exibição\" },\n showDate: { label: \"Mostrar Data\", inputType: \"checkbox\", group: \"Exibição\" },\n showCategory: { label: \"Mostrar Categoria\", inputType: \"checkbox\", group: \"Exibição\" },\n posts: { label: \"Posts\", inputType: \"text\", readOnly: true, group: \"Dados\" },\n },\n};\n\n// Auto-registro\ncomponentRegistry.register(blogRecentPostsBlock);\n"],"names":["blogRecentPostsBlock","componentRegistry"],"mappings":";AAGO,MAAMA,IAAwC;AAAA,EACnD,MAAM;AAAA,EACN,MAAM;AAAA,EACN,aAAa;AAAA,EACb,UAAU;AAAA,EACV,UAAU;AAAA,EACV,cAAc;AAAA,IACZ,OAAO;AAAA,IACP,OAAO;AAAA,IACP,eAAe;AAAA,IACf,UAAU;AAAA,IACV,cAAc;AAAA,IACd,OAAO,CAAA;AAAA,EAAC;AAAA,EAEV,eAAe;AAAA,IACb,OAAO,EAAE,OAAO,UAAU,WAAW,QAAQ,OAAO,WAAA;AAAA,IACpD,OAAO,EAAE,OAAO,cAAc,WAAW,UAAU,KAAK,GAAG,KAAK,IAAI,OAAO,WAAA;AAAA,IAC3E,eAAe,EAAE,OAAO,qBAAqB,WAAW,YAAY,OAAO,WAAA;AAAA,IAC3E,UAAU,EAAE,OAAO,gBAAgB,WAAW,YAAY,OAAO,WAAA;AAAA,IACjE,cAAc,EAAE,OAAO,qBAAqB,WAAW,YAAY,OAAO,WAAA;AAAA,IAC1E,OAAO,EAAE,OAAO,SAAS,WAAW,QAAQ,UAAU,IAAM,OAAO,QAAA;AAAA,EAAQ;AAE/E;AAGAC,EAAkB,SAASD,CAAoB;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blogTagCloud.d.ts","sourceRoot":"","sources":["../../../../../src/engine/registry/blocks/sections/blogTagCloud.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG9C,eAAO,MAAM,iBAAiB,EAAE,eAwB/B,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { componentRegistry as t } from "../../registry.js";
|
|
2
|
+
const e = {
|
|
3
|
+
type: "blogTagCloud",
|
|
4
|
+
name: "Nuvem de Tags",
|
|
5
|
+
description: "Widget com tags dos posts do blog",
|
|
6
|
+
category: "sections",
|
|
7
|
+
pluginId: "blog",
|
|
8
|
+
defaultProps: {
|
|
9
|
+
title: "Tags",
|
|
10
|
+
tags: [],
|
|
11
|
+
variant: "badges"
|
|
12
|
+
},
|
|
13
|
+
inspectorMeta: {
|
|
14
|
+
title: { label: "Título", inputType: "text", group: "Conteúdo" },
|
|
15
|
+
variant: {
|
|
16
|
+
label: "Estilo",
|
|
17
|
+
inputType: "select",
|
|
18
|
+
options: [
|
|
19
|
+
{ value: "badges", label: "Badges" },
|
|
20
|
+
{ value: "list", label: "Lista" }
|
|
21
|
+
],
|
|
22
|
+
group: "Exibição"
|
|
23
|
+
},
|
|
24
|
+
tags: { label: "Tags", inputType: "text", readOnly: !0, group: "Dados" }
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
t.register(e);
|
|
28
|
+
export {
|
|
29
|
+
e as blogTagCloudBlock
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=blogTagCloud.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blogTagCloud.js","sources":["../../../../../src/engine/registry/blocks/sections/blogTagCloud.ts"],"sourcesContent":["import { BlockDefinition } from \"../../types\";\nimport { componentRegistry } from \"../../registry\";\n\nexport const blogTagCloudBlock: BlockDefinition = {\n type: \"blogTagCloud\",\n name: \"Nuvem de Tags\",\n description: \"Widget com tags dos posts do blog\",\n category: \"sections\",\n pluginId: \"blog\",\n defaultProps: {\n title: \"Tags\",\n tags: [],\n variant: \"badges\",\n },\n inspectorMeta: {\n title: { label: \"Título\", inputType: \"text\", group: \"Conteúdo\" },\n variant: {\n label: \"Estilo\",\n inputType: \"select\",\n options: [\n { value: \"badges\", label: \"Badges\" },\n { value: \"list\", label: \"Lista\" },\n ],\n group: \"Exibição\",\n },\n tags: { label: \"Tags\", inputType: \"text\", readOnly: true, group: \"Dados\" },\n },\n};\n\n// Auto-registro\ncomponentRegistry.register(blogTagCloudBlock);\n"],"names":["blogTagCloudBlock","componentRegistry"],"mappings":";AAGO,MAAMA,IAAqC;AAAA,EAChD,MAAM;AAAA,EACN,MAAM;AAAA,EACN,aAAa;AAAA,EACb,UAAU;AAAA,EACV,UAAU;AAAA,EACV,cAAc;AAAA,IACZ,OAAO;AAAA,IACP,MAAM,CAAA;AAAA,IACN,SAAS;AAAA,EAAA;AAAA,EAEX,eAAe;AAAA,IACb,OAAO,EAAE,OAAO,UAAU,WAAW,QAAQ,OAAO,WAAA;AAAA,IACpD,SAAS;AAAA,MACP,OAAO;AAAA,MACP,WAAW;AAAA,MACX,SAAS;AAAA,QACP,EAAE,OAAO,UAAU,OAAO,SAAA;AAAA,QAC1B,EAAE,OAAO,QAAQ,OAAO,QAAA;AAAA,MAAQ;AAAA,MAElC,OAAO;AAAA,IAAA;AAAA,IAET,MAAM,EAAE,OAAO,QAAQ,WAAW,QAAQ,UAAU,IAAM,OAAO,QAAA;AAAA,EAAQ;AAE7E;AAGAC,EAAkB,SAASD,CAAiB;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/engine/registry/blocks/sections/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,OAAO,CAAC;AACtB,cAAc,WAAW,CAAC;AAC1B,cAAc,OAAO,CAAC;AACtB,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/engine/registry/blocks/sections/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,OAAO,CAAC;AACtB,cAAc,WAAW,CAAC;AAC1B,cAAc,OAAO,CAAC;AACtB,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GridRenderer.d.ts","sourceRoot":"","sources":["../../../../../src/engine/render/renderers/layout/GridRenderer.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"GridRenderer.d.ts","sourceRoot":"","sources":["../../../../../src/engine/render/renderers/layout/GridRenderer.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAGzD,wBAAgB,UAAU,CACxB,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,MAAM,GACZ,KAAK,CAAC,SAAS,CAgCjB"}
|
|
@@ -1,22 +1,25 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import
|
|
3
|
-
import { renderBlockNode as
|
|
4
|
-
function
|
|
5
|
-
const { cols: r = 3, gap:
|
|
6
|
-
return /* @__PURE__ */
|
|
7
|
-
"
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
1
|
+
import { jsxs as c, jsx as i } from "react/jsx-runtime";
|
|
2
|
+
import n from "react";
|
|
3
|
+
import { renderBlockNode as g } from "../../renderNodeImpl.js";
|
|
4
|
+
function x(e, o) {
|
|
5
|
+
const { cols: r = 3, colTemplate: t, gap: s = "1rem", children: p = [] } = e.props, l = typeof r == "number" ? r : r.lg || r.md || r.sm || 3, a = t || `repeat(${l}, 1fr)`, d = t ? `@media (max-width: 767px) { #grid-${e.id} { grid-template-columns: 1fr !important; } }` : "";
|
|
6
|
+
return /* @__PURE__ */ c(n.Fragment, { children: [
|
|
7
|
+
d && /* @__PURE__ */ i("style", { children: d }),
|
|
8
|
+
/* @__PURE__ */ i(
|
|
9
|
+
"div",
|
|
10
|
+
{
|
|
11
|
+
id: `grid-${e.id}`,
|
|
12
|
+
style: {
|
|
13
|
+
display: "grid",
|
|
14
|
+
gridTemplateColumns: a,
|
|
15
|
+
gap: s
|
|
16
|
+
},
|
|
17
|
+
children: p.map((m) => /* @__PURE__ */ i(n.Fragment, { children: g(m, o + 1) }, m.id))
|
|
18
|
+
}
|
|
19
|
+
)
|
|
20
|
+
] }, e.id);
|
|
18
21
|
}
|
|
19
22
|
export {
|
|
20
|
-
|
|
23
|
+
x as renderGrid
|
|
21
24
|
};
|
|
22
25
|
//# sourceMappingURL=GridRenderer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GridRenderer.js","sources":["../../../../../src/engine/render/renderers/layout/GridRenderer.tsx"],"sourcesContent":["/**\n * Grid Renderer\n * Renderiza bloco de grid com CSS Grid\n */\n\nimport React from \"react\";\nimport { GridBlock } from \"../../../schema/siteDocument\";\nimport { renderBlockNode } from \"../../renderNodeImpl\";\n\nexport function renderGrid(\n block: GridBlock,\n depth: number,\n): React.ReactNode {\n const { cols = 3, gap = \"1rem\", children = [] } = block.props;\n\n const gridCols =\n typeof cols === \"number\" ? cols : cols.lg || cols.md || cols.sm || 3;\n\n return (\n <div\n
|
|
1
|
+
{"version":3,"file":"GridRenderer.js","sources":["../../../../../src/engine/render/renderers/layout/GridRenderer.tsx"],"sourcesContent":["/**\n * Grid Renderer\n * Renderiza bloco de grid com CSS Grid\n * Suporte a colTemplate para templates customizados (ex: \"1fr 320px\")\n */\n\nimport React from \"react\";\nimport { GridBlock } from \"../../../schema/siteDocument\";\nimport { renderBlockNode } from \"../../renderNodeImpl\";\n\nexport function renderGrid(\n block: GridBlock,\n depth: number,\n): React.ReactNode {\n const { cols = 3, colTemplate, gap = \"1rem\", children = [] } = block.props;\n\n const gridCols =\n typeof cols === \"number\" ? cols : cols.lg || cols.md || cols.sm || 3;\n\n const gridTemplateColumns = colTemplate || `repeat(${gridCols}, 1fr)`;\n\n // When colTemplate is used, add responsive style to collapse to 1fr on mobile\n const responsiveStyle = colTemplate\n ? `@media (max-width: 767px) { #grid-${block.id} { grid-template-columns: 1fr !important; } }`\n : \"\";\n\n return (\n <React.Fragment key={block.id}>\n {responsiveStyle && <style>{responsiveStyle}</style>}\n <div\n id={`grid-${block.id}`}\n style={{\n display: \"grid\",\n gridTemplateColumns,\n gap,\n }}\n >\n {children.map((child) => (\n <React.Fragment key={child.id}>\n {renderBlockNode(child, depth + 1)}\n </React.Fragment>\n ))}\n </div>\n </React.Fragment>\n );\n}\n"],"names":["renderGrid","block","depth","cols","colTemplate","gap","children","gridCols","gridTemplateColumns","responsiveStyle","jsxs","React","jsx","child","renderBlockNode"],"mappings":";;;AAUO,SAASA,EACdC,GACAC,GACiB;AACjB,QAAM,EAAE,MAAAC,IAAO,GAAG,aAAAC,GAAa,KAAAC,IAAM,QAAQ,UAAAC,IAAW,CAAA,MAAOL,EAAM,OAE/DM,IACJ,OAAOJ,KAAS,WAAWA,IAAOA,EAAK,MAAMA,EAAK,MAAMA,EAAK,MAAM,GAE/DK,IAAsBJ,KAAe,UAAUG,CAAQ,UAGvDE,IAAkBL,IACpB,qCAAqCH,EAAM,EAAE,kDAC7C;AAEJ,SACE,gBAAAS,EAACC,EAAM,UAAN,EACE,UAAA;AAAA,IAAAF,KAAmB,gBAAAG,EAAC,WAAO,UAAAH,EAAA,CAAgB;AAAA,IAC5C,gBAAAG;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,IAAI,QAAQX,EAAM,EAAE;AAAA,QACpB,OAAO;AAAA,UACL,SAAS;AAAA,UACT,qBAAAO;AAAA,UACA,KAAAH;AAAA,QAAA;AAAA,QAGD,UAAAC,EAAS,IAAI,CAACO,wBACZF,EAAM,UAAN,EACE,UAAAG,EAAgBD,GAAOX,IAAQ,CAAC,EAAA,GADdW,EAAM,EAE3B,CACD;AAAA,MAAA;AAAA,IAAA;AAAA,EACH,EAAA,GAfmBZ,EAAM,EAgB3B;AAEJ;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BlogPostDetailRenderer.d.ts","sourceRoot":"","sources":["../../../../../src/engine/render/renderers/sections/BlogPostDetailRenderer.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAwB1B,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,GAAG,GAAG,KAAK,CAAC,SAAS,
|
|
1
|
+
{"version":3,"file":"BlogPostDetailRenderer.d.ts","sourceRoot":"","sources":["../../../../../src/engine/render/renderers/sections/BlogPostDetailRenderer.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAwB1B,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,GAAG,GAAG,KAAK,CAAC,SAAS,CAgShE"}
|