Virhe tapahtui prosessoidessa esitysmallia.
Failed to "?eval" string with this error:

---begin-message---
Syntax error in ?eval-ed string in line 1, column 77:
Lexical error: encountered "u" (117), after "\"Henkil\u00f6 pit\u00e4\u00e4 k\u00e4siss\u00e4\u00e4n esitett\u00e4, jossa lukee \\".
---end-message---

The failing expression:
==> image?eval  [in template "43104#43145#2794039" at line 42, column 38]

----
FTL stack trace ("~" means nesting-related):
	- Failed at: #assign imageJson = image?eval  [in template "43104#43145#2794039" at line 42, column 17]
----
1<#assign 
2    portlet_preferences = portletDisplay.getPortletPreferences() 
3    portlet_use_custom_title = getterUtil.getString(portlet_preferences.getValue("portletSetupUseCustomTitle", "")) 
4    portlet_title = htmlUtil.escape(portletDisplay.getTitle()) 
5    portletId = portletDisplay.instanceId 
6    headingSize = 2 
7/> 
8 
9<#assign scopeGroupTreePath = themeDisplay.getScopeGroup().treePath?split('/') /> 
10<#assign pirhaGroupId = scopeGroupTreePath[1]?number /> 
11 
12<#assign images_folder = themeDisplay.getPathThemeImages() /> 
13<#assign pageUrl = ""> 
14 
15<#if entries?has_content> 
16    <#if portlet_use_custom_title == 'true' > 
17        <h2 class="portlet-title-custom" id="heading-${portletId}">${portlet_title}</h2> 
18        <#assign headingSize = 3 /> 
19    </#if> 
20 
21    <div class="pirha-news-list list-with-images grid-list"> 
22        <#list entries as curEntry> 
23            <#assign assetRenderer = curEntry.getAssetRenderer() /> 
24            <#assign pageUrl = assetPublisherHelper.getAssetViewURL(renderRequest, renderResponse, assetRenderer, entry, true)> 
25 
26            <#assign article = assetRenderer.getArticle() /> 
27 
28            <#assign title = webArticleHelper.getArticleFieldValue(article, "title") /> 
29            <#assign lead = webArticleHelper.getArticleFieldValue(article, "lead") /> 
30            <#assign content = webArticleHelper.getArticleFieldValue(article, "content") /> 
31            <#assign image = webArticleHelper.getArticleFieldValue(article, "mainImage") /> 
32            <#assign publishDate = curEntry.publishDate?string('d.M.yyyy') /> 
33            <#assign publishDateISO = curEntry.publishDate?string("yyyy-MM-dd") /> 
34 
35            <#assign articleDDMStructure = article.getDDMStructure() /> 
36            <#assign typeCategories = webArticleHelper.getAssetCategoriesForArticleInVocabulary(article, pirhaGroupId, "Tyyppi") /> 
37 
38            <#assign imageURL = "" /> 
39            <#assign imageAlt = '' /> 
40 
41            <#if image?has_content && image != ''> 
42                <#assign imageJson = image?eval /> 
43 
44                <#if imageJson.url?? && imageJson.url != ""> 
45                    <#assign imageURL = imageJson.url /> 
46                </#if> 
47 
48                <#if imageJson.alt?? && imageJson.alt != ""> 
49                    <#assign imageAlt = imageJson.alt /> 
50                </#if> 
51 
52                <#if imageJson.fileEntryId?? && imageJson.fileEntryId != ""> 
53                    <#assign fileEntryId = imageJson.fileEntryId /> 
54                </#if> 
55            </#if> 
56 
57            <div class="pirha-news-list-item mb-4" data-article-id="${article.id}"> 
58                <div class="list-item-image ratio ratio-16x9"> 
59                    <img src="${imageURL}" alt="${imageAlt}" class="image-cover" /> 
60                </div> 
61 
62                <h${headingSize} class="pirha-news-list--heading"><a href="${pageUrl}">${title}</a></h${headingSize}> 
63 
64                <div class="meta"> 
65                    <#if typeCategories?has_content> 
66                        <#list typeCategories as category> 
67                            <#if category.getTitle('fi_FI') == 'Uutinen'> 
68                                <#assign categoryColor = 'color--orange-dark' /> 
69                            <#elseif category.getTitle('fi_FI') == 'Blogi'> 
70                                <#assign categoryColor = 'color--violet' /> 
71                            <#else> 
72                                <#assign categoryColor = 'color--blue' /> 
73                            </#if> 
74 
75                            <span class="meta-text category ${categoryColor}">${category.getTitle(locale)}</span> 
76                        </#list> 
77                    </#if> 
78 
79                    <span data-date="${publishDateISO}">${publishDate}</span> 
80                </div> 
81            </div> 
82        </#list> 
83    </div> 
84</#if> 
85 
86<@liferay_util["body-bottom"] outputKey="bodybottomNewsList"> 
87<script> 
88    document.addEventListener("DOMContentLoaded", (event) => { 
89        const listOne = document.querySelector('.pirha-bg-row .pirha-news-list.list-with-images'); 
90        const listTwo = document.querySelector('.pirha-bg-row .pirha-news-list.list-simple'); 
91 
92        <#--  // Find the parent portlet columns  --> 
93        const columnOne = listOne.closest('.portlet-column'); 
94        const columnTwo = listTwo.closest('.portlet-column'); 
95 
96        if (!columnOne || !columnTwo) { 
97            return; 
98
99 
100        <#--  // Check if columns are adjacent  --> 
101        const columns = Array.from(document.querySelectorAll('.pirha-bg-row .portlet-column')); 
102        const indexOne = columns.indexOf(columnOne); 
103        const indexTwo = columns.indexOf(columnTwo); 
104 
105        <#-- // Only run if columns are adjacent --> 
106        if (Math.abs(indexOne - indexTwo) !== 1) { 
107            return; 
108
109 
110        <#--  // Ignore first two  --> 
111        const listOneItems = Array.from(listOne.querySelectorAll('.pirha-news-list-item')).slice(2); 
112 
113        function getListTwoItems() { 
114            return Array.from(listTwo.querySelectorAll('.item')); 
115
116 
117        <#--  // Helper to get date timestamp  --> 
118        function getDate(item) { 
119            const el = item.querySelector('.meta span[data-date]'); 
120            return el ? new Date(el.dataset.date).getTime() : 0; 
121
122 
123        <#--  // Helper to get title text  --> 
124        function getTitle(item) { 
125            const el = item.querySelector('.heading a, .pirha-news-list--heading a'); 
126            return el ? el.textContent.trim().toLowerCase() : ''; 
127
128 
129        <#--  // Comparator: date DESC, title ASC  --> 
130        function compareItems(a, b) { 
131            const dateDiff = getDate(b) - getDate(a); 
132            if (dateDiff !== 0) return dateDiff; 
133            return getTitle(a).localeCompare(getTitle(b)); 
134
135 
136        <#--  // Clone and insert for mobile  --> 
137        listOneItems.forEach(item => { 
138            const title = getTitle(item); 
139 
140            <#--  // Mark original item as mobile-hidden  --> 
141            item.classList.add('item--mobile-hidden'); 
142 
143            <#--  // Clone and mark as desktop-hidden (only visible on mobile)  --> 
144            const clone = item.cloneNode(true); 
145            clone.classList.add('item--desktop-hidden'); 
146 
147            <#--  // Remove all images from clone  --> 
148            clone.querySelectorAll('.list-item-image').forEach(img => img.remove()); 
149 
150            <#--  // Find correct insert position  --> 
151            const insertBefore = getListTwoItems().find(existing => compareItems(clone, existing) < 0); 
152 
153            if (insertBefore) { 
154                listTwo.insertBefore(clone, insertBefore); 
155            } else { 
156                listTwo.appendChild(clone); 
157
158        }); 
159    }) 
160</script> 
161 
162<style> 
163    .item--mobile-hidden { 
164        display: none; 
165
166 
167    .item--desktop-hidden { 
168        display: none; 
169
170 
171    <#--  /* Mobile view */  --> 
172    @media (max-width: 767px) { 
173        .item--mobile-hidden { 
174            display: none !important; 
175
176 
177        .item--desktop-hidden { 
178            display: block !important; 
179
180
181 
182    <#--  /* Desktop view */  --> 
183    @media (min-width: 768px) { 
184        .item--mobile-hidden { 
185            display: block !important; 
186
187 
188        .item--desktop-hidden { 
189            display: none !important; 
190
191
192</style> 
193</@> 

Päivitetty 21.3.2025