Praktiska rokasgrāmata CEL izteiksmju rakstīšanai CMS.
Praktiska rokasgrāmata CEL izteiksmju rakstīšanai CMS.
CEL (Common Expression Language — kopējā izteiksmju valoda) ir viegla skriptu valoda, kas iebūvēta mūsu CMS. Tā ļauj rakstīt dinamiskas izteiksmes, kas var iegūt datus no dokumentiem, nolasīt URL parametrus un aprēķināt vērtības izpildes laikā.
Lūk, kas notiek, kad tiek izpildīts CEL skripts:
Jūsu skripts Dzinējs Rezultāts
| | |
v v v
documents.get("article", "intro") --> Iegūst no datubāzes --> { headline: "Welcome", body: "..." }
.headline --> Izgūst lauku --> "Welcome"
Uztveriet CEL kā tikai lasāmu vaicājumu valodu. Tā nevar modificēt neko datubāzē — tā tikai nolasa datus un atgriež aprēķinātu rezultātu. Tāpēc to var droši izmantot jebkur CMS.
Katrai CEL izteiksmei ir pieejamas trīs lietas:
| Objekts | Kas tas ir | Piemērs |
|---|---|---|
documents | Iegūst jebkuru dokumentu no CMS | documents.get("country", "us") |
meta | Informācija par pašreizējo pieprasījumu (lokāle, URL parametri) | meta.locale, meta.params.slug |
schema | Pašreizējā dokumenta lauku definīcijas | schema.fields |
docRakstot CEL izteiksmes dokumentu redaktorā, pašreizējā dokumenta lauku vērtībām var piekļūt, izmantojot objektu doc. Tas ļauj izveidot aprēķināmos laukus un atsauces starp laukiem.
// Piekļuve pašreizējā dokumenta cenas laukam
doc.price
// Kopējās summas aprēķins no pašreizējā dokumenta laukiem
doc.price * doc.quantity
// Nosacījums, kas balstīts uz pašreizējā dokumenta statusu
doc.status == "published" ? doc.title : "Draft: " + doc.title
Objekts doc satur visas rediģētā dokumenta lauku vērtības. Tas ir noderīgi:
doc.price * doc.quantity);Viena no jaudīgākajām CEL funkcijām ir dokumentu iegūšana no jebkuras vietas jūsu CMS.
Sintakse: documents.get(schemaName, identifier)
Pieņemsim, ka jums ir article dokuments ar identifikatoru "welcome-post":
// Saglabāts CMS kā: article / welcome-post
{
"headline": "Welcome to Our Platform",
"author": "Sarah Chen",
"body": "We're excited to announce...",
"tags": ["announcement", "news"]
}
Lai iegūtu visu dokumentu:
documents.get("article", "welcome-post")
Atgriež: visu dokumentu.
Lai iegūtu tikai virsrakstu:
documents.get("article", "welcome-post").headline
Atgriež: "Welcome to Our Platform"
Lai iegūtu autoru:
documents.get("article", "welcome-post").author
Atgriež: "Sarah Chen"
Ja jūsu lapai ir dinamiskie maršruti, piemēram, /articles/[slug], varat izmantot meta.params, lai iegūtu URL parametru un atrastu pareizo dokumentu.
Ja lietotājs apmeklē /articles/welcome-post:
documents.get("article", meta.params.slug).headline
Atgriež: "Welcome to Our Platform"
Šādi tiek veidotas dinamiskas lapas — viens un tas pats CEL skripts darbojas jebkuram rakstam, izmantojot URL norādīto slug.
Sintakse: documents.find(schemaName) vai documents.find(schemaName, filter)
// Iegūt visas valstis
documents.find("country")
Atgriež: dokumentu masīvu.
// Iegūt valstis ar filtru
documents.find("country", { "where": { "code": "us" } })
CEL atbalsta tulkota dokumenta satura iegūšanu divos veidos: automātisku tulkošanu pēc lokāles un skaidri norādīta tulkojuma meklēšanu.
Ja meta.locale ir iestatīts, piemēram, no maršruta parametriem vai lietotāja izvēlēm, documents.get() automātiski apvieno tulkoto saturu:
// Ja meta.locale ir "fr", tiek atgriezts franču tulkojums, apvienots ar pamata dokumentu
documents.get("greeting", "welcome").headline
Darbības princips:
meta.locale nav "en" vai "en-US", tulkojums tiek meklēts translations tabulā.{ ...baseContent, ...translatedContent }.Tas nozīmē, ka tulkotie lauki aizstāj pamata laukus, bet netulkotie lauki tiek paņemti no pamata dokumenta.
Ja jāiegūst konkrēts tulkojums neatkarīgi no pašreizējās lokāles:
Sintakse: documents.translated(schemaName, identifier, locale)
// Vienmēr iegūt tulkojumu spāņu valodā
documents.translated("greeting", "welcome", "es").headline
// Iegūt tulkojumu, balstoties uz URL parametru
documents.translated("product", meta.params.id, meta.params.lang).description
// Salīdzināt tulkojumus
documents.translated("article", "intro", "en").title + " / " + documents.translated("article", "intro", "fr").title
// Pamata dokuments: greeting / welcome
{ "headline": "Welcome", "subheadline": "Welcome to our platform" }
// Tulkojums (valoda: "fr")
{ "headline": "Bienvenue", "subheadline": "Bienvenue sur notre plateforme" }
// Tulkojums (valoda: "es")
{ "headline": "Bienvenido", "subheadline": "Bienvenido a nuestra plataforma" }
CEL skripti:
// Ar meta.locale = "fr"
documents.get("greeting", "welcome").headline
// Atgriež: "Bienvenue"
// Skaidri norādīts tulkojums spāņu valodā
documents.translated("greeting", "welcome", "es").headline
// Atgriež: "Bienvenido"
// Rezerves variants, ja tulkojuma nav
documents.translated("greeting", "welcome", meta.params.lang) != null
? documents.translated("greeting", "welcome", meta.params.lang).headline
: documents.get("greeting", "welcome").headline
Jums ir hero-block, kuram jāparāda no article dokumenta iegūts virsraksts.
CEL skripts varoņa bloka virsraksta laukā:
documents.get("article", "homepage-hero").headline
Rezultāts: varonis parāda "Build Faster, Ship Smarter".
Veidojat lapu /countries/[code] un vēlaties parādīt pilnu valsts nosaukumu:
documents.get("country", meta.params.code).name
Apmeklējot /countries/us, meta.params.code ir "us", bet rezultāts ir "United States".
meta.locale == "ar-SA" ? "Welcome, everyone" : "Welcome"
Ja lokāle ir "ar-SA", tiek atgriezts "Welcome, everyone"; citādi — "Welcome".
documents.get("country", documents.get("article", "us-news").countryCode).name
Vispirms tiek iegūts raksts, pēc tam tā countryCode lauks un visbeidzot attiecīgās valsts name lauks.
documents.get("article", meta.params.slug) != null
? documents.get("article", meta.params.slug).headline
: "Article Not Found"
Lauka esamību var pārbaudīt šādi:
documents.get("article", "intro").author != null
? documents.get("article", "intro").author
: "Unknown Author"
"featured" in documents.get("article", "welcome-post").tags
Atgriež true, ja rakstam ir tags "featured".
Pirmā taga iegūšana:
documents.get("article", "welcome-post").tags[0]
Saraksta elementu skaita iegūšana:
size(documents.get("article", "welcome-post").tags)
Parametriskie maršruti ir svarīgi dinamisku, lokalizētu lapu veidošanai. Ja definējat maršruta shēmu, piemēram, /{lang}/landingPage, CMS izvelk parametrus no URL un padara tos pieejamus, izmantojot meta.params.
Maršruti izmanto sintaksi :paramName vai {paramName}, lai definētu dinamiskos segmentus:
| Shēma | Piemēra URL | Iegūtie parametri |
|---|---|---|
/:lang/landingPage | /ko/landingPage | { lang: "ko" } |
/{country}/{lang}/products | /us/en/products | { country: "us", lang: "en" } |
/articles/:slug | /articles/welcome-post | { slug: "welcome-post" } |
Katru maršruta parametru var piesaistīt dokumentu shēmai validācijai:
{
"pattern": "/{lang}/landingPage",
"param_bindings": {
"lang": "language"
}
}
CMS izvelk segmentu lang, validē to pret language shēmu un, ja tas ir derīgs, padara pilno dokumentu pieejamu atrisinātajos parametros.
Lokalizēta satura iegūšanas CEL skripts:
documents.get("greeting", meta.params.lang).headline
Maršrutam /{country}/{lang}/products:
// Iegūt valsts nosaukumu
documents.get("country", meta.params.country).name
// Iegūt valstij atbilstošu produktu sarakstu
documents.find("product", { "where": { "country": meta.params.country } })
// Parādīt valstij atbilstošu sveicienu lietotāja valodā
documents.get("greeting", meta.params.lang).headline + " from " + documents.get("country", meta.params.country).name
CMS validē parametrus hierarhiski: vispirms country, pēc tam lang, kā arī pēc izvēles pārbauda, vai lang atrodas country.languages[] masīvā.
meta.segments nodrošina neapstrādāto URL ceļu kā masīvu. Tas ir noderīgi, ja nepieciešama piekļuve segmentiem pēc to pozīcijas, nevis nosaukta parametra.
| URL ceļš | meta.segments |
|---|---|
/articles/tech/ai-news | ["articles", "tech", "ai-news"] |
/ko/landingPage | ["ko", "landingPage"] |
/us/en/products/featured | ["us", "en", "products", "featured"] |
/ | [] |
| Lietojums | Ieteicamā pieeja |
|---|---|
| Nosaukti parametri no maršruta shēmas | meta.params.lang |
| Piekļuve pēc pozīcijas | meta.segments[0] |
| Ceļa dziļuma iegūšana | size(meta.segments) |
| Pārbaude, vai ceļā ir segments | "admin" in meta.segments |
Piemēri:
// Iegūt pirmo segmentu (bieži valodas kodu)
meta.segments[0]
// Pārbaudīt ceļa dziļumu
size(meta.segments) > 2 ? "deep" : "shallow"
// Pārbaudīt, vai atrodamies administrēšanas sadaļā
"admin" in meta.segments ? "admin mode" : "public mode"
// Rezerves variants, ja parametrs nav piesaistīts
has(meta.params.lang) ? meta.params.lang : meta.segments[0]
Objekts meta satur visu pašreizējā pieprasījuma kontekstu:
| Īpašība | Tips | Apraksts |
|---|---|---|
meta.locale | string | Pašreizējais lokāles kods, piemēram, "en-US", "ko-KR", "ar-SA" |
meta.params | Record<string, string> | No URL shēmas izvilktie maršruta parametri |
meta.segments | string[] | URL ceļš sadalīts segmentos |
meta.docId | string | null | Pašreizējā dokumenta UUID; jauniem dokumentiem — null |
meta.title | string | Pašreizējā dokumenta virsraksts |
Lokāles kods atbilst BCP 47 formātam:
// Pārbaudīt lokāli virziena no labās uz kreiso valodām
meta.locale == "ar-SA" || meta.locale == "he-IL" ? "rtl" : "ltr"
// Iegūt tikai valodas daļu
meta.locale.split("-")[0] // Nav atbalstīts — tā vietā izmantojiet meta.params.lang
Maršruta parametri vienmēr ir virknes. CMS tos pirms novērtēšanas validē pret piesaistītajām shēmām:
// Piekļūt nosauktam parametram
meta.params.lang // "ko"
meta.params.country // "us"
meta.params.slug // "welcome-post"
// Pārbaudīt, vai parametrs pastāv
has(meta.params.category) // true/false
// Izmantot dokumenta iegūšanai
documents.get("greeting", meta.params.lang)
documents.ref("airports").get(meta.params.code)
Neapstrādātie URL segmenti kā masīvs:
meta.segments[0] // Pirmais segments
meta.segments[1] // Otrais segments
size(meta.segments) // Segmentu skaits
"products" in meta.segments // Vai ceļā ir "products"?
Pašreizējā dokumenta UUID, kas noder pašreferences skriptiem:
meta.docId != null ? "editing" : "creating new"
meta.docId != null ? documents.get("article", meta.docId).status : "draft"
Pašreizējā dokumenta virsraksts:
"Editing: " + meta.title
meta.title.contains("Draft") ? "work in progress" : "published"
Ja shēma ir zināma, bet identifikators ir dinamisks, var izmantot skaidrāku sintaksi:
// Tradicionālā pieeja
documents.get("airports", meta.params.code).name
// Izmantojot ref()
documents.ref("airports").get(meta.params.code).name
Abas pieejas ir līdzvērtīgas, taču ref() skaidrāk parāda dinamisko daļu.
documents.get("schema", "identifier") // Iegūt vienu dokumentu
documents.get("schema", "id").fieldName // Iegūt konkrētu lauku
documents.find("schema") // Iegūt visus dokumentus
documents.find("schema", { "where": {...}}) // Filtrēts vaicājums
documents.ref("schema").get(identifier) // Ķēdē savienota meklēšana
documents.translated("schema", "id", "fr") // Iegūt ar konkrētu lokāli
meta.locale // "en-US", "ar-SA" u. c.
meta.params.xyz // URL parametrs ar nosaukumu "xyz"
meta.segments // URL ceļš kā masīvs
meta.segments[0] // Pirmais ceļa segments
meta.docId // Pašreizējā dokumenta ID (vai null)
meta.title // Pašreizējā dokumenta virsraksts
doc.fieldName // Pašreizējā dokumenta lauka vērtība
// Salīdzināšana
== != < <= > >=
// Loģika
&& || !
// Trīskāršais operators
condition ? valueIfTrue : valueIfFalse
// Piederība
"value" in listOrMap
size(list) // Elementu skaits
size(string) // Virknes garums
"text".startsWith("te") // true
"text".endsWith("xt") // true
"text".contains("ex") // true
has(object.property) // Pārbaudīt, vai īpašība pastāv
hasProperty(obj, "key") // Alternatīva objekta atslēgas pārbaudes sintakse
Ja kaut kas neizdodas, var tikt parādīta kāda no šīm kļūdām:
| Kļūda | Nozīme |
|---|---|
SYNTAX_ERROR | Kļūda skriptā (trūkst pēdiņu vai ir nepareizs operators) |
TYPE_ERROR | Tiek kombinēti nesaderīgi tipi |
RUNTIME_ERROR | Skripts tika palaists, bet radās problēma (piemēram, nedefinēts mainīgais) |
FETCH_LIMIT_EXCEEDED | Tiek iegūts pārāk daudz dokumentu (ne vairāk kā 50) |
TIMEOUT | Skripts izpildījās pārāk ilgi (ne vairāk kā 5 sekundes) |
AST_DEPTH_EXCEEDED | Izteiksme ir pārāk dziļi ligzdota (maksimālais dziļums: 50) |
SCRIPT_TOO_LONG | Skripts pārsniedz 5000 rakstzīmju ierobežojumu |
CEL dzinējs ir veidots ar iespēju to paplašināt. Plānotās nākotnes iespējas ietver:
// Nākotnē: ārējo pakalpojumu izsaukšana, izmantojot MCP
mcp.translate(meta.params.text, "en", meta.params.lang)
mcp.analyze(documents.get("article", meta.params.id).body)
// Nākotnē: satura ģenerēšana ar MI
aı.summarize(documents.get("article", meta.params.id).body, 100)
ai.translate(meta.params.text, meta.params.targetLang)
ai.classify(meta.params.input, ["positive", "negative", "neutral"])
Šīs iespējas tiks pievienotas, izmantojot reģistrēto funkciju sistēmu, saglabājot atpakaļsaderību ar esošajiem skriptiem.
documents. vai meta., un redaktors parādīs pieejamās iespējas.documents.get("schema", "id"), pēc tam pievienojiet .fieldName.!= null ? ... : ....documents.get() vai documents.find() tiek ieskaitīts 50 iegūšanas reižu limitā.has(meta.params.category).Šajā sadaļā aprakstīti sarežģītāki modeļi dokumentu sasaistīšanai un relāciju satura struktūru veidošanai.
Vienkāršākajā variantā viens dokuments atsaucas uz citu pēc identifikatora:
// Raksts glabā autora ID; iegūt autora vārdu
documents.get("author", documents.get("article", "intro").authorId).name
// Tradicionālā pieeja
documents.get("country", documents.get("airport", meta.params.code).countryCode).name
// Izmantojot ref()
documents.ref("country").get(documents.get("airport", meta.params.code).countryCode).name
// Lidosta → Valsts → Reģions → Kontinents
documents.get("continent",
documents.get("region",
documents.get("country",
documents.get("airport", meta.params.code).countryCode
).regionCode
).continentCode
).name
// Iegūt lidostai atbilstošu lokalizētu valsts nosaukumu
documents.translated("country",
documents.get("airport", meta.params.code).countryCode,
meta.params.lang
).name
Dokuments glabā ID, kas norāda uz citu dokumentu.
// article / tech-news
{ "title": "Tech Update", "authorId": "author-123", "categoryId": "cat-tech" }
// Atrisināt autora vārdu
documents.get("author", documents.get("article", meta.params.slug).authorId).name
// Atrisināt kategoriju ar rezerves vērtību
documents.get("article", meta.params.slug).categoryId != null
? documents.get("category", documents.get("article", meta.params.slug).categoryId).name
: "Uncategorized"
Dokumenti atsaucas cits uz citu ar semantiskiem kodiem, nevis UUID.
// Lidosta → Valsts → Valūta
documents.get("currency",
documents.get("country",
documents.get("airport", meta.params.code).countryCode
).currencyCode
).symbol
Izmantojiet doc aprēķināmajiem laukiem, kas atsaucas uz citiem dokumentiem, balstoties uz pašreizējā dokumenta vērtībām.
// Produkta dokumentā iegūt saistītās kategorijas informāciju
documents.get("category", doc.categoryId).description
// Aprēķināt piegādes izmaksas pēc produkta izcelsmes valsts
documents.get("shipping-rates", doc.originCountry).baseRate * doc.weight
Ja dokumenti atsaucas cits uz citu, uzmanieties no iegūšanas reižu limita.
documents.find("article", { "where": { "authorId": documents.get("article", meta.params.slug).authorId } })
Ja lauks var atsaukties uz dažādām shēmām:
documents.get("content-block", "hero-1").sourceType == "article"
? documents.get("article", documents.get("content-block", "hero-1").sourceId).headline
: documents.get("product", documents.get("content-block", "hero-1").sourceId).name
Katrs documents.get(), documents.find() un documents.ref().get() izsaukums tiek izsekots kešatmiņas anulēšanai. Kad mainās atsauces dokuments, CMS zina, kuras CEL izteiksmes jānovērtē atkārtoti.
Izsekojamās atkarības ietver:
schema:identifier — konkrēta dokumenta atkarība;schema:identifier — tas pats, izmantojot ķēdes sintaksi;schema:* — shēmas līmeņa atkarība.Šajā piemērā tiek izveidota daudzvalodu galvenā lapa, kas pieejama vietnē /{lang}/landingPage.
CMS administrēšanas vidē izveidojiet pielāgotu shēmu ar nosaukumu greeting:
{
"name": "greeting",
"fields": [
{ "name": "code", "type": "string", "required": true },
{ "name": "headline", "type": "string", "required": true },
{ "name": "subheadline", "type": "string" },
{ "name": "ctaText", "type": "string" },
{ "name": "ctaUrl", "type": "string" }
]
}
Izveidojiet dokumentu katrai valodai, izmantojot iepriekš minēto struktūru.
Izveidojiet lapu ar šādu konfigurāciju:
/{lang}/landingPagelang uz language komponenti.{
"lang": "language"
}
Pievienojiet maršrutam varoņa bloku ar šādiem CEL skriptiem:
// Virsraksts
documents.get("greeting", meta.params.lang).headline
// Apakšvirsraksts
documents.get("greeting", meta.params.lang).subheadline
// CTA teksts
documents.get("greeting", meta.params.lang).ctaText
// CTA URL
documents.get("greeting", meta.params.lang).ctaUrl
Pievienojiet visaptverošu maršrutu. ParametricRoutePage atrisina lapu, izvelk meta.params no URL, servera pusē novērtē CEL piesaistes un attēlo katru bloku, izmantojot reģistru.
// app/[...slug]/page.tsx
import ParametricRoutePage from 'cms-renderer/lib/renderer';
import { registry } from '@/lib/registry';
import { cmsConfig } from '@/lib/cms-config';
export const dynamic = 'force-static';
interface PageProps {
params: Promise<{ slug: string[] }>;
}
export default async function Page({ params }: PageProps) {
const { slug } = await params;
return (
<ParametricRoutePage
registry={registry}
apiKey={cmsConfig.apiKey}
websiteId={cmsConfig.websiteId}
cmsUrl={cmsConfig.cmsUrl}
params={Promise.resolve({ slug })}
/>
);
}
Apmeklējiet URL, lai skatītu lokalizētu saturu:
| URL | Paredzamais virsraksts |
|---|---|
/ko/landingPage | 환영 |
/en/landingPage | Welcome |
/ja/landingPage | いらっしゃいませ |
Apmeklējot /ko/landingPage:
/{lang}/landingPage shēmu.meta.params.lang = "ko"."ko" pastāv language shēmā.documents.get("greeting", meta.params.lang) tiek atrisināti līdz korejiešu saturam.interface CelMeta {
/** Pašreizējais lokāles kods (piemēram, 'en-US') */
locale: string;
/** No URL izvilktie maršruta parametri */
params: Record<string, string>;
/** URL ceļa segmenti */
segments: string[];
/** Pašreizējā dokumenta ID (ja tiek rediģēts esošs dokuments) */
docId: string | null;
/** Pašreizējā dokumenta virsraksts */
title: string;
}
Funkcija extractParams apstrādā URL ceļus:
Shēma: /{country}/{lang}/products
Ceļš: /us/en/products
Algoritms:
1. Normalizēt abus ceļus (noņemt beigu slīpsvītras)
2. Sadalīt segmentos: ["us", "en", "products"] un ["{country}", "{lang}", "products"]
3. Salīdzināt segmentu skaitu (tam jābūt vienādam)
4. Katram segmentu pārim:
- Ja shēma sākas ar : vai {}, izvilkt parametru
- Pretējā gadījumā segmentiem precīzi jāsakrīt
5. Atgriezt: { country: "us", lang: "en" }
// Vienkārša piesaiste (meklēšanai izmanto lauku "code")
{ "lang": "language" }
// Detalizēta piesaiste (pielāgots slug lauks)
{
"lang": {
"schemaName": "language",
"slugField": "code"
},
"slug": {
"schemaName": "article",
"slugField": "slug"
}
}
Iegūstot datus ar documents.get(schema, identifier):
id.content.code lauku.content.slug lauku.title lauku.Tas ļauj elastīgi atsaukties uz dokumentiem, izmantojot jebkuru unikālu identifikatoru.