@kidecms/core 0.1.0 → 0.1.2
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/ai.js +4 -1
- package/package.json +1 -1
- package/dist/blocks.js +0 -110
package/dist/ai.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { streamText } from "ai";
|
|
2
1
|
import { getStorage, readEnv } from "./runtime";
|
|
2
|
+
const getStreamText = async () => (await import("ai")).streamText;
|
|
3
3
|
export function isAiEnabled() {
|
|
4
4
|
return !!(readEnv("AI_PROVIDER") && readEnv("AI_API_KEY"));
|
|
5
5
|
}
|
|
@@ -19,6 +19,7 @@ export async function streamAltText(imageUrl, filename) {
|
|
|
19
19
|
if (!image) {
|
|
20
20
|
throw new Error(`Image not found: ${imageUrl}`);
|
|
21
21
|
}
|
|
22
|
+
const streamText = await getStreamText();
|
|
22
23
|
return streamText({
|
|
23
24
|
model,
|
|
24
25
|
messages: [
|
|
@@ -45,6 +46,7 @@ export async function streamSeoDescription(content) {
|
|
|
45
46
|
Title: ${content.title}
|
|
46
47
|
${content.excerpt ? `Excerpt: ${content.excerpt}` : ""}
|
|
47
48
|
${content.body ? `Body preview: ${content.body.substring(0, 500)}` : ""}`;
|
|
49
|
+
const streamText = await getStreamText();
|
|
48
50
|
return streamText({ model, prompt });
|
|
49
51
|
}
|
|
50
52
|
export async function streamTranslation(content) {
|
|
@@ -63,5 +65,6 @@ ${content.text}`;
|
|
|
63
65
|
|
|
64
66
|
${content.text}`;
|
|
65
67
|
}
|
|
68
|
+
const streamText = await getStreamText();
|
|
66
69
|
return streamText({ model, prompt });
|
|
67
70
|
}
|
package/package.json
CHANGED
package/dist/blocks.js
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import { cmsImage, cmsSrcset } from "./image";
|
|
2
|
-
import { renderRichText } from "./richtext";
|
|
3
|
-
function esc(value) {
|
|
4
|
-
return String(value ?? "")
|
|
5
|
-
.replace(/&/g, "&")
|
|
6
|
-
.replace(/</g, "<")
|
|
7
|
-
.replace(/>/g, ">")
|
|
8
|
-
.replace(/"/g, """);
|
|
9
|
-
}
|
|
10
|
-
function parseJson(value) {
|
|
11
|
-
if (typeof value === "string") {
|
|
12
|
-
try {
|
|
13
|
-
return JSON.parse(value);
|
|
14
|
-
}
|
|
15
|
-
catch {
|
|
16
|
-
return value;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
return value;
|
|
20
|
-
}
|
|
21
|
-
function isRichText(value) {
|
|
22
|
-
const parsed = parseJson(value);
|
|
23
|
-
return parsed && typeof parsed === "object" && parsed.type === "root";
|
|
24
|
-
}
|
|
25
|
-
function isImageUrl(value) {
|
|
26
|
-
const stringValue = String(value ?? "");
|
|
27
|
-
return stringValue.startsWith("/uploads/") || stringValue.startsWith("http://") || stringValue.startsWith("https://");
|
|
28
|
-
}
|
|
29
|
-
function isImageArray(value) {
|
|
30
|
-
const parsed = parseJson(value);
|
|
31
|
-
return Array.isArray(parsed) && parsed.length > 0 && parsed.every((entry) => isImageUrl(entry));
|
|
32
|
-
}
|
|
33
|
-
function isRepeaterArray(value) {
|
|
34
|
-
const parsed = parseJson(value);
|
|
35
|
-
return Array.isArray(parsed) && parsed.length > 0 && typeof parsed[0] === "object" && parsed[0] !== null;
|
|
36
|
-
}
|
|
37
|
-
function renderImage(src) {
|
|
38
|
-
if (src.startsWith("/uploads/")) {
|
|
39
|
-
return `<img src="${esc(cmsImage(src, 1024))}" srcset="${esc(cmsSrcset(src))}" sizes="(max-width: 768px) 100vw, 768px" alt="" loading="lazy" class="h-auto w-full rounded-lg object-cover" />`;
|
|
40
|
-
}
|
|
41
|
-
return `<img src="${esc(src)}" alt="" loading="lazy" class="w-full rounded-lg object-cover" />`;
|
|
42
|
-
}
|
|
43
|
-
function renderFieldValue(key, value) {
|
|
44
|
-
if (value === null || value === undefined || value === "")
|
|
45
|
-
return "";
|
|
46
|
-
const parsed = parseJson(value);
|
|
47
|
-
if (isRichText(value)) {
|
|
48
|
-
return `<div class="prose">${renderRichText(parsed)}</div>`;
|
|
49
|
-
}
|
|
50
|
-
if (isImageArray(value)) {
|
|
51
|
-
const images = Array.isArray(parsed) ? parsed : [];
|
|
52
|
-
return `<div class="grid gap-4">${images.map((src) => renderImage(String(src))).join("")}</div>`;
|
|
53
|
-
}
|
|
54
|
-
if (isImageUrl(value)) {
|
|
55
|
-
return renderImage(String(value));
|
|
56
|
-
}
|
|
57
|
-
if (isRepeaterArray(value)) {
|
|
58
|
-
const items = Array.isArray(parsed) ? parsed : [];
|
|
59
|
-
let html = `<div class="grid gap-3">`;
|
|
60
|
-
for (const item of items) {
|
|
61
|
-
html += `<div class="rounded-lg border border-gray-200 bg-gray-50 px-5 py-4">`;
|
|
62
|
-
for (const [itemKey, itemValue] of Object.entries(item)) {
|
|
63
|
-
if (itemKey === "_key" || itemKey === "id" || !itemValue)
|
|
64
|
-
continue;
|
|
65
|
-
const className = itemKey.includes("description") || itemKey.includes("answer") || itemKey.includes("body")
|
|
66
|
-
? "m-0 text-gray-500"
|
|
67
|
-
: "mb-1 font-semibold";
|
|
68
|
-
html += `<p class="${className}">${esc(itemValue)}</p>`;
|
|
69
|
-
}
|
|
70
|
-
html += `</div>`;
|
|
71
|
-
}
|
|
72
|
-
html += `</div>`;
|
|
73
|
-
return html;
|
|
74
|
-
}
|
|
75
|
-
if (key === "heading" || key === "title") {
|
|
76
|
-
return `<h2 class="mb-3 text-xl font-semibold">${esc(value)}</h2>`;
|
|
77
|
-
}
|
|
78
|
-
if (key === "eyebrow" || key === "label") {
|
|
79
|
-
return `<p class="mb-1 text-xs font-semibold uppercase tracking-wide text-teal-700">${esc(value)}</p>`;
|
|
80
|
-
}
|
|
81
|
-
if (key === "ctaLabel" || key === "ctaHref") {
|
|
82
|
-
return "";
|
|
83
|
-
}
|
|
84
|
-
return `<p class="text-gray-500">${esc(value)}</p>`;
|
|
85
|
-
}
|
|
86
|
-
export function renderBlock(block) {
|
|
87
|
-
const { type: _type, _key, ...fields } = block;
|
|
88
|
-
let html = `<section>`;
|
|
89
|
-
if (fields.eyebrow) {
|
|
90
|
-
html += renderFieldValue("eyebrow", fields.eyebrow);
|
|
91
|
-
}
|
|
92
|
-
for (const key of ["heading", "title"]) {
|
|
93
|
-
if (fields[key]) {
|
|
94
|
-
html += renderFieldValue(key, fields[key]);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
for (const [key, value] of Object.entries(fields)) {
|
|
98
|
-
if (["eyebrow", "heading", "title", "ctaLabel", "ctaHref"].includes(key))
|
|
99
|
-
continue;
|
|
100
|
-
html += renderFieldValue(key, value);
|
|
101
|
-
}
|
|
102
|
-
if (fields.ctaLabel && fields.ctaHref) {
|
|
103
|
-
html += `<a href="${esc(fields.ctaHref)}" class="mt-4 inline-block rounded-md bg-teal-700 px-4 py-2 text-sm text-white no-underline">${esc(fields.ctaLabel)}</a>`;
|
|
104
|
-
}
|
|
105
|
-
html += `</section>`;
|
|
106
|
-
return html;
|
|
107
|
-
}
|
|
108
|
-
export function renderBlocks(blocks) {
|
|
109
|
-
return blocks.map(renderBlock).join("");
|
|
110
|
-
}
|