RTF文字與AEM Headless
多行文字欄位是「內容片段」的資料型別,可讓作者建立RTF文字內容。 對其他內容(例如影像或其他內容片段)的參考可動態地在文字流程中內嵌插入。 單行文字欄位是另一個應用於簡單文字元素的內容片段資料型別。
AEM的GraphQL API提供強大的功能,可將RTF傳回HTML、純文字或純JSON。 JSON表示法功能強大,因為可讓使用者端應用程式完全掌控內容呈現方式。
多行編輯器
在內容片段編輯器中,多行文字欄位的功能表列為作者提供標準的RTF格式功能,例如 粗體、斜體 和底線。 以全熒幕模式開啟多行欄位,可啟用其他格式化工具,例如段落文字、尋找和取代、拼字檢查等等。
多行文字資料型別 multi-line-data-type
定義您的內容片段模型時,請使用 多行文字 資料型別來啟用RTF撰寫。
可以設定多行欄位的幾個屬性。
Render as 屬性可以設為:
- 文字區域 — 呈現單一多行欄位
- 多個欄位 — 呈現多個多行欄位
預設型別 可以設定為:
- RTF
- Markdown
- 純文字
預設型別 選項會直接影響編輯體驗,並決定RTF工具是否存在。
您也可以檢查 允許片段參考 並設定 允許的內容片段模型,以啟用其他內容片段的內嵌參考。
如果要將內容當地語系化,請核取 可翻譯 方塊。 只有RTF和純文字可以當地語系化。 如需詳細資訊,請參閱使用當地語系化內容。
使用GraphQL API提供RTF回應
建立GraphQL查詢時,開發人員可以從多行欄位中從html
、plaintext
、markdown
和json
選擇不同的回應型別。
開發人員可以在內容片段編輯器中使用JSON預覽,以顯示可使用GraphQL API傳回之目前內容片段的所有值。
GraphQL持續查詢
選取多行欄位的json
回應格式,可在使用RTF文字內容時提供最大的彈性。 RTF內容會以JSON節點型別陣列的形式傳送,且可根據使用者端平台唯一處理。
以下是名為main
且包含段落的多行欄位的JSON回應型別: "此段落包含 重要 內容。」中,「重要」標示為 bold。
query ($path: String!) {
articleByPath(_path: $path)
{
item {
_path
main {
json
}
}
}
}
_path
篩選器中使用的$path
變數需要內容片段的完整路徑(例如/content/dam/wknd/en/magazine/sample-article
)。
GraphQL回應:
{
"data": {
"articleByPath": {
"item": {
"_path": "/content/dam/wknd/en/magazine/sample-article",
"main": {
"json": [
{
"nodeType": "paragraph",
"content": [
{
"nodeType": "text",
"value": "This is a paragraph that includes "
},
{
"nodeType": "text",
"value": "important",
"format": {
"variants": [
"bold"
]
}
},
{
"nodeType": "text",
"value": " content. "
}
]
}
]
}
}
}
}
}
其他範例
以下是名為main
且包含段落之多行欄位的幾個回應型別範例:「這是包含 重要 內容的段落。」 其中「重要」標示為 bold。
GraphQL持續查詢:
code language-graphql |
---|
|
GraphQL回應:
code language-json |
---|
|
GraphQL持續查詢:
code language-graphql |
---|
|
GraphQL回應:
code language-json |
---|
|
GraphQL持續查詢:
code language-graphql |
---|
|
GraphQL回應:
code language-json |
---|
|
plaintext
演算選項會移除任何格式。
轉譯RTF文字JSON回應 render-multiline-json-richtext
多行欄位的RTF文字JSON回應會結構化為階層式樹狀結構。 每個物件或節點代表RTF文字的不同HTML區塊。
以下是多行文字欄位的JSON回應範例。 請注意,每個物件或節點都包含一個nodeType
,代表RTF中的HTML區塊,例如paragraph
、link
和text
。 每個節點選擇性地包含content
,這是包含目前節點之任何子系的子陣列。
"json": [// root "content" or child nodes
{
"nodeType": "paragraph", // node for a paragraph
"content": [ // children of current node
{
"nodeType": "text", // node for a text
"value": "This is the first paragraph. "
},
{
"nodeType": "link",
"data": {
"href": "http://www.adobe.com"
},
"value": "An external link"
}
],
},
{
"nodeType": "paragraph",
"content": [
{
"nodeType": "text",
"value": "This is the second paragraph."
},
],
},
]
呈現多行json
回應的最簡單方法是,處理回應中的每個物件或節點,然後處理目前節點的任何子系。 遞回函式可用於周遊JSON樹狀結構。
以下是說明遞回周遊方法的範常式式碼。 範例是以JavaScript為基礎,使用React的JSX,不過程式設計概念可套用至任何語言。
// renderNodeList - renders a list of nodes
function renderNodeList(childNodes) {
if(!childNodes) {
// null check
return null;
}
return childNodes.map(node, index) => {
return renderNode(node);
}
}
renderNodeList
是接受childNodes
陣列的遞回函式。 然後陣列中的每個節點會傳遞至函式renderNode
,如果節點有子系,則函式會呼叫renderNodeList
。
// renderNode - renders an individual node
function renderNode(node) {
// if the current node has children, recursively process them
const children = node.content ? renderNodeList(node.content) : null;
// use a map to render the current node based on its nodeType
return nodeMap[node.nodeType]?.(node, children);
}
renderNode
函式需要名為node
的單一物件。 節點可以有子系,這些子系會使用上述renderNodeList
函式遞回處理。 最後,使用nodeMap
根據節點的nodeType
來轉譯節點的內容。
// nodeMap - object literal that maps a JSX response based on a given key (nodeType)
const nodeMap = {
'paragraph': (node, children) => <p>{children}</p>,
'link': node => <a href={node.data.href} target={node.data.target}>{node.value}</a>,
'text': node => node.value,
'unordered-list': (node, children) => <ul>{children}</ul>,
'ordered-list': (node, children) => <ol>{children}</ol>,
'list-item': (node, children) => <li>{children}</li>,
...
}
nodeMap
是用作地圖的JavaScript物件常值。 每個「金鑰」代表不同的nodeType
。 node
和children
的引數可以傳入產生節點的函式。 此範例中使用的傳回型別是JSX,但方法可調整為建置表示HTML內容的字串常值。
完整程式碼範例
可在WKND GraphQL React範例中找到可重複使用的RTF轉譯公用程式。
- renderRichText.js — 公開函式
mapJsonRichText
的可重複使用公用程式。 想要將RTF文字JSON回應轉譯為React JSX的元件可使用此公用程式。 - AdventureDetail.js — 發出包含RTF文字的GraphQL請求的元件範例。 元件使用
mapJsonRichText
公用程式來轉譯RTF文字和任何參考。
新增內嵌參考至RTF insert-fragment-references
「多行」欄位可讓作者在RTF文字流中插入AEM Assets的影像或其他數位資產。
上述熒幕擷圖描繪使用 插入資產 按鈕在多行欄位中插入的影像。
對其他內容片段的參考也可以使用 插入內容片段 按鈕連結或插入多行欄位中。
上面的熒幕擷圖描繪了插入多行欄位中的另一個內容片段,洛杉磯滑冰公園終極指南。 可插入欄位中的內容片段型別是由內容片段模式中多行資料型別中的 允許的內容片段模式 設定所控制。
使用GraphQL查詢內嵌參考
GraphQL API可讓開發人員建立查詢,查詢中包含有關插入多行欄位中的任何參考的其他屬性。 JSON回應包含一個單獨的_references
物件,其中列出這些額外的屬性。 JSON回應可讓開發人員完全掌控如何呈現參考資料或連結,而不必處理教條式HTML。
例如,您可能想要:
- 包含自訂路由邏輯,用於在實作單頁應用程式(例如使用React路由器或Next.js)時管理其他內容片段的連結
- 使用指向AEM Publish環境的絕對路徑作為
src
值來轉譯內嵌影像。 - 決定如何使用其他自訂屬性呈現對其他內容片段的嵌入參考。
建構GraphQL查詢時使用json
傳回型別並包含_references
物件:
GraphQL持續查詢:
query ($path: String!) {
articleByPath(_path: $path, _assetTransform: { format: JPG, preferWebp: true })
{
item {
_path
main {
json
}
}
_references {
...on ImageRef {
_dynamicUrl
__typename
}
...on ArticleModel {
_path
author
__typename
}
}
}
}
在上述查詢中,main
欄位會傳回為JSON。 _references
物件包含片段,用於處理任何型別為ImageRef
或型別為ArticleModel
的參考。
JSON回應:
{
"data": {
"articleByPath": {
"item": {
"_path": "/content/dam/wknd/en/magazine/sample-article",
"main": {
"json": [
{
"nodeType": "paragraph",
"content": [
{
"nodeType": "text",
"value": "This is a paragraph that includes "
},
{
"nodeType": "text",
"value": "important",
"format": {
"variants": [
"bold"
]
}
},
{
"nodeType": "text",
"value": " content. "
}
]
},
{
"nodeType": "paragraph",
"content": [
{
"nodeType": "reference",
"data": {
"path": "/content/dam/wknd/en/activities/climbing/sport-climbing.jpg",
"mimetype": "image/jpeg"
}
}
]
},
{
"nodeType": "paragraph",
"content": [
{
"nodeType": "text",
"value": "Reference another Content Fragment: "
},
{
"nodeType": "reference",
"data": {
"href": "/content/dam/wknd/en/magazine/la-skateparks/ultimate-guide-to-la-skateparks",
"type": "fragment"
},
"value": "Ultimate Guide to LA Skateparks"
}
]
}
]
}
},
"_references": [
{
"_dynamicUrl": "/adobe/dynamicmedia/deliver/dm-aid--dd42d814-88ec-4c4d-b5ef-e3dc4bc0cb42/sport-climbing.jpg?preferwebp=true",
"__typename": "ImageRef"
},
{
"_path": "/content/dam/wknd/en/magazine/la-skateparks/ultimate-guide-to-la-skateparks",
"author": "Stacey Roswells",
"__typename": "ArticleModel"
}
]
}
}
}
JSON回應包含參考以"nodeType": "reference"
插入RTF中的位置。 然後_references
物件會包含每個參考。
以RTF文字呈現內嵌參考
若要呈現內嵌參考,可展開呈現多行JSON回應中說明的遞回方法。
其中nodeMap
是轉譯JSON節點的對應。
const nodeMap = {
'reference': (node, children) => {
// variable for reference in _references object
let reference;
// asset reference
if (node.data.path) {
// find reference based on path
reference = references.find( ref => ref._path === node.data.path);
}
// Fragment Reference
if (node.data.href) {
// find in-line reference within _references array based on href and _path properties
reference = references.find( ref => ref._path === node.data.href);
}
// if reference found, merge properties of reference and current node, then return render method of it using __typename property
return reference ? renderReference[reference.__typename]({...reference, ...node}) : null;
}
}
高階方法是在Multli Line JSON回應中nodeType
等於reference
時檢查。 接著可以呼叫包含GraphQL回應中傳回的_references
物件的自訂轉譯函式。
然後可以將內嵌參考路徑與_references
物件中的對應專案比較,並且可以呼叫另一個自訂對應renderReference
。
const renderReference = {
// node contains merged properties of the in-line reference and _references object
'ImageRef': (node) => {
// when __typename === ImageRef
return <img src={node._dynamicUrl} alt={'in-line reference'} />
},
'ArticleModel': (node) => {
// when __typename === ArticleModel
return <Link to={`/article:${node._path}`}>{`${node.value}`}</Link>;
}
...
}
_references
物件的__typename
可用來將不同的參考型別對應到不同的轉譯器函式。
完整程式碼範例
您可以在AdventureDetail.js中找到寫入自訂參考轉譯器的完整範例,作為WKND GraphQL React範例的一部分。
端對端範例
前文影片顯示端對端範例:
- 更新內容片段模型的多行文字欄位以允許片段參考
- 使用內容片段編輯器在多行文字欄位中包含影像和對另一個片段的引用。
- 建立GraphQL查詢,其中包含以JSON格式的多行文字回應及使用的任何
_references
。 - 撰寫會呈現RTF回應內嵌參考的React SPA。