- Liferay npm Bundler
- Understanding the Liferay npm Bundler Loader
- Changes Between Bundler 1.x and 2.x
- Default Bundler Loaders
- How AMD Loader Configuration is Exported
- How the Bundler Publishes npm Packages
- How JavaScript Modules are Formatted for AMD
- Understanding Bundler Configuration Presets
- Understanding the npmbundlerrc Structure
- OSGi Bundles and npm Package Structure
- Bundler Migration Guide
An error occurred while processing the template.
For "." left-hand operand: Expected a hash, but this has evaluated to a string (wrapper: f.t.SimpleScalar): ==> structuredContent [in template "57868206215768#32483061#35456003" at line 56, column 34] ---- FTL stack trace ("~" means nesting-related): - Failed at: taxonomyCategoryBriefs = structuredCo... [in template "57868206215768#32483061#35456003" at line 56, column 9] ----
1<script>
2 const _addEventListener = (selectors) => {
3 var elements = document.querySelectorAll(selectors);
4
5 elements.forEach((element) => {
6 element.addEventListener("click", (event) => {
7 event.preventDefault();
8
9 const anchorElement = document.getElementById(element.getAttribute("id").replace("toc-", ""));
10
11 if (anchorElement) {
12 window.history.pushState(
13 {},
14 "",
15 "#" + element.getAttribute("id").replace("toc-", "")
16 );
17 scrollToElement(anchorElement);
18 }
19 });
20 });
21 }
22
23 const scrollToElement = (element) => {
24 if (!element) return;
25
26 window.scrollTo({
27 behavior: "smooth",
28 top: element.getBoundingClientRect().top + window.scrollY - 190,
29 });
30 };
31
32 window.addEventListener('load', function() {
33 _addEventListener("h1 a, h2 a, h3 a");
34 _addEventListener(".toc li a");
35
36 if (window.location.hash) {
37 const hashLocation = document.getElementById(window.location.hash.substring(1));
38
39 if (hashLocation) {
40 setTimeout(() => {
41 scrollToElement(hashLocation);
42 }, 100);
43 }
44 }
45 });
46</script>
47
48<#assign
49 journalArticleId = .vars["reserved-article-id"].data
50
51 structuredContent = restClient.get("/headless-delivery/v1.0/sites/${groupId}/structured-contents/by-key/${journalArticleId}?nestedFields=embeddedTaxonomyCategory")
52
53 showChildrenCards = showChildrenCards.getData()?boolean
54 taxonomyCategoriesMap = {}
55 taxonomyVocabularies = []
56 taxonomyCategoryBriefs = structuredContent.taxonomyCategoryBriefs
57
58 navigationJSONObject = jsonFactoryUtil.createJSONObject(htmlUtil.unescape(navigation.getData()?trim))
59
60 breadcrumbJSONArray = navigationJSONObject.getJSONArray("breadcrumb")
61 childrenJSONArray = navigationJSONObject.getJSONArray("children")
62/>
63
64<#list taxonomyCategoryBriefs as taxonomyCategoryBrief>
65 <#assign taxonomyVocabularyName = taxonomyCategoryBrief.embeddedTaxonomyCategory.parentTaxonomyVocabulary.name />
66
67 <#if !taxonomyVocabularies?seq_contains(taxonomyVocabularyName)>
68 <#assign taxonomyVocabularies = taxonomyVocabularies + [taxonomyVocabularyName] />
69 </#if>
70
71 <#if taxonomyCategoriesMap[taxonomyVocabularyName]?has_content>
72 <#assign taxonomyCategoriesMap = taxonomyCategoriesMap +
73 {
74 taxonomyVocabularyName:
75 taxonomyCategoriesMap[taxonomyVocabularyName] + [{
76 "categoryId": taxonomyCategoryBrief.taxonomyCategoryId,
77 "categoryName": taxonomyCategoryBrief.taxonomyCategoryName
78 }]
79 }
80 />
81 <#else>
82 <#assign taxonomyCategoriesMap = taxonomyCategoriesMap +
83 {
84 taxonomyVocabularyName:
85 [{
86 "categoryId": taxonomyCategoryBrief.taxonomyCategoryId,
87 "categoryName": taxonomyCategoryBrief.taxonomyCategoryName
88 }]
89 }
90 />
91 </#if>
92</#list>
93
94<article class="learn-article">
95 <div class="d-flex flex-column">
96 <div class="learn-article-breadcrumbs">
97 <div class="learn-article-breadcrumbs-content">
98 <div class="align-items-baseline d-flex justify-content-between mb-3">
99 <ul
100 aria-label="breadcrumb navigation"
101 class="learn-article-breadcrumb"
102 role="navigation"
103 >
104 <li>
105 <a href="/"><@clay["icon"] symbol="home-full" /></a>
106 </li>
107
108 <#if breadcrumbJSONArray?has_content>
109 <#list breadcrumbJSONArray.length()-1..0 as i>
110 <#assign breadcrumbJSONObject = breadcrumbJSONArray.getJSONObject(i)! />
111 <li>
112 <#if breadcrumbJSONObject??
113 && breadcrumbJSONObject["title"]?has_content
114 && breadcrumbJSONObject["url"]?has_content >
115 <a href='${breadcrumbJSONObject.getString("url")}'>${breadcrumbJSONObject.getString("title")}</a>
116 </#if>
117 </li>
118 </#list>
119 </#if>
120
121 <li>
122 ${navigationJSONObject.getJSONObject("self").getString("title")}
123 </li>
124 </ul>
125
126 <div class="submit-feedback">
127 <a
128 class="text-decoration-none"
129 href="https://liferay.dev/c/portal/login?redirect=https://liferay.dev/ask/questions/liferay-learn-feedback/new"
130 >
131 ${languageUtil.get(locale, "submit-feedback", "Submit Feedback")}
132 <@clay["icon"] symbol="message-boards" />
133 </a>
134 </div>
135 </div>
136 </div>
137 </div>
138
139 <div class="learn-article-wrapper">
140 <div class="language-log learn-article-content">
141 <#if (content.getData())??>
142 ${content.getData()}
143 </#if>
144
145 <#if showChildrenCards && childrenJSONArray.length() gt 0>
146 <div class="learn-card-container">
147 <#list 0..childrenJSONArray.length()-1 as i>
148 <#assign childJSONObject = childrenJSONArray.getJSONObject(i) />
149
150 <div class="learn-card">
151 <a href="${childJSONObject.getString("url")}">
152 <h4>${childJSONObject.getString("title")}</h4>
153 </a>
154
155 <#if childJSONObject.getJSONArray("children")?has_content>
156 <#assign grandchildrenJSONArray = childJSONObject.getJSONArray("children") />
157
158 <div class="mt-2 subsection">
159 <#list 0..grandchildrenJSONArray.length()-1 as j>
160 <#assign grandchildJSONObject = grandchildrenJSONArray.getJSONObject(j)! />
161
162 <#if grandchildJSONObject??
163 && grandchildJSONObject["title"]?has_content
164 && grandchildJSONObject["url"]?has_content >
165 <a href="${grandchildJSONObject["url"]!}">
166 ${grandchildJSONObject["title"]!}
167 </a>
168 </#if>
169 </#list>
170 </div>
171 </#if>
172 </div>
173 </#list>
174 </div>
175 </#if>
176 <div class="learn-article-categories-tags">
177 <#list taxonomyVocabularies as vocabulary>
178 <div class="align-items-baseline d-flex mt-2">
179 <div class="learn-article-category-title mr-2">
180 ${vocabulary}:
181 </div>
182 <#list taxonomyCategoriesMap[vocabulary]?sort_by("categoryName") as taxonomyCategory>
183 <div class="learn-article-category-tag mr-2">
184 <a
185 class="label tag-container"
186 href="/search?${vocabulary?lower_case?replace(" ", "-", "r")}=${taxonomyCategory.categoryId}"
187 >
188 <span>${taxonomyCategory.categoryName}</span>
189 </a>
190 </div>
191 </#list>
192 </div>
193 </#list>
194 </div>
195
196 <div class="article-related-how-to">
197 <#setting url_escaping_charset='UTF-8' />
198
199 <#if (structuredContent.keywords?has_content && structuredContent.keywords?size > 0)>
200 <#assign
201 queryParams = {
202 "fields": "dateModified,id,title",
203 "filter": "(knowledgeArticleType eq 'howTo') and (status eq 0) and (sourceTeam eq 'Enablement')",
204 "pageSize": "3",
205 "search": structuredContent.keywords[0],
206 "sort": "dateModified:desc"
207 }
208 queryParts = []
209 />
210
211 <#list queryParams?keys as key>
212 <#assign
213 value = queryParams[key]
214
215 queryParts = queryParts + ["${key?url}=${value?url}"]
216 />
217 </#list>
218
219 <#assign knowledgeArticles = restClient.get("/c/p2s3knowledgearticles/?" + queryParts?join('&')) />
220
221 <#if (knowledgeArticles.totalCount)?has_content && (knowledgeArticles.totalCount > 0)>
222 <div class="how-to-container">
223 <div class="how-to-container-header">
224 ${languageUtil.get(locale, 'how-to-related-to-this-article')}
225 </div>
226
227 <div class="how-to-cards-container" id="how-to-cards-container">
228 <#assign currentURL = portalUtil.getCurrentURL(request) >
229 <#list knowledgeArticles.items as knowledgeArticle>
230 <a class="how-to-card" href="${currentURL}/l/${knowledgeArticle.id}/">
231 <div class="how-to-card-header">
232 ${knowledgeArticle.title!}
233 </div>
234
235 <div class="how-to-card-date-published">
236 <#assign date = knowledgeArticle.dateModified?datetime("yyyy-MM-dd'T'HH:mm:ss'Z'") />
237
238 ${languageUtil.get(locale, 'published-date')}: ${date?string["MMM dd, yy hh:mm a"]}
239 </div>
240 </a>
241 </#list>
242 </div>
243 </div>
244 </#if>
245 </#if>
246 </div>
247 </div>
248
249 <div class="learn-article-page-nav">
250 <ul class="nav nav-stacked toc" id="articleTOC"></ul>
251 </div>
252 </div>
253 </div>
254</article>
255
256<style>
257 .how-to-card {
258 align-items: flex-start;
259 background: var(--color-brand-primary-lighten-6, #FBFCFE);
260 border: 1px solid var(--color-brand-primary-lighten-5, #E7EFFF);
261 border-radius: 0.75rem;
262 box-sizing: border-box;
263 cursor: pointer;
264 display: flex;
265 flex-direction: column;
266 gap: 0.5rem;
267 isolation: isolate;
268 justify-content: space-between;
269 order: 0;
270 padding: 1rem;
271 width: 100%;
272 }
273
274 .how-to-card:hover {
275 background: var(--color-action-primary-hover-10, #EDF3FE);
276 border: 1px solid var(--color-action-primary-hover, #0053F0);
277 border-radius: 0.625rem;
278 }
279
280 .how-to-card-date-published {
281 align-items: center;
282 align-self: stretch;
283 color: var(--color-neutral-8, #54555F);
284 display: flex;
285 flex: none;
286 flex-grow: 0;
287 font-family: 'Source Sans 3';
288 font-size: 0.75rem;
289 font-style: normal;
290 font-weight: 400;
291 line-height: 1rem;
292 }
293
294 .how-to-card-header {
295 align-items: center;
296 align-self: stretch;
297 color: var(--color-brand-primary, #0B5FFF);
298 display: flex;
299 flex: none;
300 flex-grow: 0;
301 font-family: 'Source Sans 3';
302 font-size: 1rem;
303 font-style: normal;
304 font-weight: 600;
305 line-height: 1.5rem;
306 }
307
308 .how-to-cards-container {
309 display: flex;
310 flex-direction: row;
311 gap: 1rem;
312 width: 100%;
313 }
314
315 .how-to-container {
316 align-items: flex-start;
317 align-self: stretch;
318 background: var(--color-neutral-1, #F7F7F8);
319 border-radius: 0.75rem;
320 display: flex;
321 flex: none;
322 flex-direction: column;
323 flex-grow: 0;
324 gap: 1.5rem;
325 isolation: isolate;
326 margin: 1.5rem 0px;
327 order: 0;
328 padding: 1.5rem;
329 width: 100%;
330 }
331
332 .how-to-container-header {
333 align-items: center;
334 color: var(--color-neutral-10, #282934);
335 display: flex;
336 flex: none;
337 flex-grow: 0;
338 font-family: 'Source Sans 3';
339 font-size: 1.5rem;
340 font-style: normal;
341 font-weight: 700;
342 line-height: 1.75rem;
343 }
344
345 @media only screen and (max-width: 1200px) {
346 .how-to-cards-container {
347 flex-direction: column;
348 }
349 }
350</style>
Capabilities
Product
Education
Knowledge Base
Contact Us