Links
Contents
Rich text can link to other content in the repository, to media files, and to external URLs.
Internal links
Internal links are stored as references rather than fixed URLs, so they keep working when the target is moved or renamed — the actual URL is resolved when the content is rendered.
Appearance
In Content Studio, the HtmlArea editor provides a link dialog that allows editors to insert links to content, media and external URLs. The editor also supports editing existing links, including changing the link type and target.
Raw format
Links are stored as standard <a> elements. Internal links reference their target by ID using an Enonic-specific scheme, while external links are stored verbatim:
<!-- Internal content link -->
<a href="content://f3076b5c-ea45-4c8b-8c06-1f87b8d8cdd9">latest post</a>
<!-- Media / attachment link -->
<a href="media://download/2b6e1f0c-5a3d-4f9e-9c1a-7d8e2b4a6f10">download the PDF</a>
<!-- External link -->
<a href="https://enonic.com" target="_blank">Enonic</a>
-
content://<id>— a link to another content item. -
media://download/<id>— a link to a media file, served by the Attachment API. -
Absolute
http(s)://URLs are stored unchanged.
These references must be resolved to real URLs before rendering — see Processed output.
Processed output
Guillotine tags internal links with data-link-ref and puts a placeholder in href. Match the attribute to ref in the structured links list. Use pageUrl for page links and media.mediaUrl for file links; both provide URL components for the front-end to assemble.
{
guillotine(project: "myproject", branch: "master") {
get(key: "/articles/hello") {
... on com_example_myapp_Article {
data {
body {
processedHtml
links {
ref (1)
uri (2)
content { (3)
_path
displayName
}
pageUrl { baseUrl path queryString }
fragment
media { (4)
content { _id }
intent (5)
mediaUrl { path queryString }
}
}
}
}
}
}
}
}
| 1 | Matches the data-link-ref attribute in processedHtml, so a front-end can map each link to its target. |
| 2 | The original content:// or media:// reference. |
| 3 | The referenced content item, including the media content for a media link. |
| 4 | Populated for links to media; null for content links. |
| 5 | Either download or inline. |
{
"data": {
"guillotine": {
"get": {
"data": {
"body": {
"processedHtml": "<p>Read our <a href=\"/articles/latest-post\" data-link-ref=\"e72f48b6-a972-4133-a300-a3ab5d132800\">latest post</a>.</p>",
"links": [
{
"ref": "e72f48b6-a972-4133-a300-a3ab5d132800",
"uri": "content://f3076b5c-ea45-4c8b-8c06-1f87b8d8cdd9",
"content": {
"_path": "/articles/latest-post",
"displayName": "Latest post"
},
"pageUrl": {
"baseUrl": null,
"path": "/articles/latest-post",
"queryString": ""
},
"fragment": "",
"media": null
}
]
}
}
}
}
}
}
Rendering
For a page link, use pageUrl.baseUrl when configured, or your front-end’s base URL, then append path, queryString and fragment. Alternatively, map the path to your own routes. Without scopeKey, page URLs use the project context; select a site with scopeKey when you need its base URL and relative paths.
For a media link, concatenate your public API or media base URL with media.mediaUrl.path and media.mediaUrl.queryString. Replace the matching element’s href; do not use the placeholder as a finished URL. Handle unresolved references, whose URL fields are null.
See Guillotine rich-text links for complete rendering examples, and Front-end integration for framework integrations.