Subprefeitura Cidade Tiradentes
Um erro ocorreu enquanto processava o modelo.
The following has evaluated to null or missing:
==> cf [in template "20095#20121#170610" at line 236, column 65]
----
Tip: If the failing expression is known to legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
----
----
FTL stack trace ("~" means nesting-related):
- Failed at: ${cf.customValue.data} [in template "20095#20121#170610" at line 236, column 63]
----
1<#setting locale="pt_BR" />
2<#setting time_zone="GMT-3" />
3<#assign title=.vars["reserved-article-title"].data />
4<#assign publicationDate=.vars['reserved-article-display-date'].data />
5<#assign format="EEEE, d 'de' MMMM 'de' yyyy" />
6<#assign timeFormat="HH:mm" />
7
8<#assign publicationDate=publicationDate?datetime("EEE, d MMM yyyy HH:mm:ss Z") />
9<#assign formattedTime=publicationDate?datetime?string(timeFormat) />
10<#assign publicationDate = publicationDate?date?string(format) />
11
12<style>
13 .psp-date-title--space-between {
14 display: flex;
15 justify-content: space-between;
16 flex-direction: row;
17 gap: 4px;
18 }
19
20 @media screen and (max-width: 768px){
21 .psp-date-title--space-between {
22 flex-direction: column;
23 }
24 }
25 .social-icon {
26 width: 48px;
27 height: 48px;
28 background-size: cover;
29 display: inline-block;
30 transition: scale 0.3s ease;
31 }
32 .social-icon:hover {
33 scale: 1.2;
34 }
35 .social-icon--facebook { background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0OCA0OCI+PHBhdGggZD0iTTQyIDM3YTUgNSAwIDAgMS01IDVIMTFhNSA1IDAgMCAxLTUtNVYxMWE1IDUgMCAwIDEgNS01aDI2YTUgNSAwIDAgMSA1IDV2MjZ6IiBmaWxsPSIjM0Y1MUI1Ii8+PHBhdGggZD0iTTM0LjM2OCAyNUgzMXYxM2gtNVYyNWgtM3YtNGgzdi0yLjQxYy4wMDItMy41MDggMS40NTktNS41OSA1LjU5Mi01LjU5SDM1djRoLTIuMjg3QzMxLjEwNCAxNyAzMSAxNy42IDMxIDE4LjcyM1YyMWg0bC0uNjMyIDR6IiBmaWxsPSIjRkZGIi8+PC9zdmc+'); }
36 .social-icon--whatsapp { background-image: url('data:image/svg+xml;base64,PHN2ZyBjbGlwLXJ1bGU9ImV2ZW5vZGQiIHZpZXdCb3g9IjAgMCA0OCA0OCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJtNC44NjggNDMuMzAzIDIuNjk0LTkuODM1YTE4Ljk0MSAxOC45NDEgMCAwIDEgLTIuNTM1LTkuNDg5Yy4wMDUtMTAuNDY1IDguNTIxLTE4Ljk3OSAxOC45ODctMTguOTc5YTE4Ljg2NyAxOC44NjcgMCAwIDEgMTMuNDMgNS41NjYgMTguODY2IDE4Ljg2NiAwIDAgMSA1LjU1NiAxMy40MjhjLS4wMDQgMTAuNDY1LTguNTIyIDE4Ljk4LTE4Ljk4NiAxOC45OC0uMDAxIDAgMCAwIDAgMGgtLjAwOGExOC45NjUgMTguOTY1IDAgMCAxIC05LjA3My0yLjMxMXoiIGZpbGw9IiNmZmYiLz48cGF0aCBkPSJtNC44NjggNDMuODAzYS40OTkuNDk5IDAgMCAxIC0uNDgyLS42MzFsMi42MzktOS42MzZhMTkuNDggMTkuNDggMCAwIDEgLTIuNDk3LTkuNTU2Yy4wMDQtMTAuNzQyIDguNzQ1LTE5LjQ4IDE5LjQ4Ni0xOS40OGExOS4zNjcgMTkuMzY3IDAgMCAxIDEzLjc4NCA1LjcxMyAxOS4zNjIgMTkuMzYyIDAgMCAxIDUuNzAyIDEzLjc4MWMtLjAwNCAxMC43NDEtOC43NDYgMTkuNDgtMTkuNDg2IDE5LjQ4YTE5LjUzNSAxOS41MzUgMCAwIDEgLTkuMTQ0LTIuMjc3bC05Ljg3NSAyLjU4OWEuNDU3LjQ1NyAwIDAgMSAtLjEyNy4wMTd6IiBmaWxsPSIjZmZmIi8+PHBhdGggZD0ibTI0LjAxNCA1YTE4Ljg2NyAxOC44NjcgMCAwIDEgMTMuNDMgNS41NjYgMTguODY2IDE4Ljg2NiAwIDAgMSA1LjU1NiAxMy40MjhjLS4wMDQgMTAuNDY1LTguNTIyIDE4Ljk4LTE4Ljk4NiAxOC45OGgtLjAwOGExOC45NjUgMTguOTY1IDAgMCAxIC05LjA3My0yLjMxMWwtMTAuMDY1IDIuNjQgMi42OTQtOS44MzVhMTguOTQxIDE4Ljk0MSAwIDAgMSAtMi41MzUtOS40ODljLjAwNS0xMC40NjUgOC41MjEtMTguOTc5IDE4Ljk4Ny0xOC45NzltMC0xYy0xMS4wMTYgMC0xOS45ODIgOC45NjItMTkuOTg3IDE5Ljk3OWEyMC4wMSAyMC4wMSAwIDAgMCAyLjQ2MSA5LjYyMmwtMi41ODUgOS40MzlhLjk5OC45OTggMCAwIDAgMS4yMTkgMS4yMzFsOS42ODctMi41NGEyMC4wMjYgMjAuMDI2IDAgMCAwIDkuMTk3IDIuMjQ0YzExLjAyNCAwIDE5Ljk5LTguOTYzIDE5Ljk5NS0xOS45OGExOS44NTYgMTkuODU2IDAgMCAwIC01Ljg0OC0xNC4xMzUgMTkuODY5IDE5Ljg2OSAwIDAgMCAtMTQuMTM5LTUuODZ6IiBmaWxsPSIjY2ZkOGRjIi8+PHBhdGggZD0ibTM1LjE3NiAxMi44MzJhMTUuNjczIDE1LjY3MyAwIDAgMCAtMTEuMTU3LTQuNjI2Yy04LjcwNCAwLTE1Ljc4MyA3LjA3Ni0xNS43ODcgMTUuNzc0YTE1LjczOCAxNS43MzggMCAwIDAgMi40MTMgOC4zOTZsLjM3Ni41OTctMS41OTUgNS44MjEgNS45NzMtMS41NjYuNTc3LjM0MmExNS43NSAxNS43NSAwIDAgMCA4LjAzMiAyLjE5OWguMDA2YzguNjk4IDAgMTUuNzc3LTcuMDc3IDE1Ljc4LTE1Ljc3NmExNS42OCAxNS42OCAwIDAgMCAtNC42MTgtMTEuMTYxeiIgZmlsbD0iIzQwYzM1MSIvPjxwYXRoIGQ9Im0xOS4yNjggMTYuMDQ1Yy0uMzU1LS43OS0uNzI5LS44MDYtMS4wNjgtLjgyLS4yNzctLjAxMi0uNTkzLS4wMTEtLjkwOS0uMDExcy0uODMuMTE5LTEuMjY1LjU5NC0xLjY2MSAxLjYyMi0xLjY2MSAzLjk1NiAxLjcgNC41OSAxLjkzNyA0LjkwNiAzLjI4MiA1LjI1OSA4LjEwNCA3LjE2MWM0LjAwNyAxLjU4IDQuODIzIDEuMjY2IDUuNjkzIDEuMTg3czIuODA3LTEuMTQ3IDMuMjAyLTIuMjU1LjM5NS0yLjA1Ny4yNzctMi4yNTVjLS4xMTktLjE5OC0uNDM1LS4zMTYtLjkwOS0uNTU0cy0yLjgwNy0xLjM4NS0zLjI0Mi0xLjU0My0uNzUxLS4yMzctMS4wNjguMjM4Yy0uMzE2LjQ3NC0xLjIyNSAxLjU0My0xLjUwMiAxLjg1OS0uMjc3LjMxNy0uNTU0LjM1Ny0xLjAyOC4xMTlzLTIuMDAyLS43MzgtMy44MTUtMi4zNTRjLTEuNDEtMS4yNTctMi4zNjItMi44MS0yLjYzOS0zLjI4NS0uMjc3LS40NzQtLjAzLS43MzEuMjA4LS45NjguMjEzLS4yMTMuNDc0LS41NTQuNzEyLS44MzEuMjM3LS4yNzcuMzE2LS40NzUuNDc0LS43OTEuMTU4LS4zMTcuMDc5LS41OTQtLjA0LS44MzEuLTExNy0uMjM4LTEuMDM5LTIuNTg0LTEuNDYxLTMuNTIyeiIgZmlsbD0iI2ZmZiIgZmlsbC1ydWxlPSJldmVub2RkIi8+PC9zdmc+'); }
37 .social-icon--linkedin { background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0OCA0OCI+PHBhdGggZD0iTTQyIDM3YTUgNSAwIDAgMS01IDVIMTFhNSA1IDAgMCAxLTUtNVYxMWE1IDUgMCAwIDEgNS01aDI2YTUgNSAwIDAgMSA1IDV2MjZ6IiBmaWxsPSIjMDI4OEQxIi8+PHBhdGggZD0iTTEyIDE5aDV2MTdoLTV6bTIuNDg1LTJoLS4wMjhDMTIuOTY1IDE3IDEyIDE1Ljg4OCAxMiAxNC40OTkgMTIgMTMuMDggMTIuOTk1IDEyIDE0LjUxNCAxMmMxLjUyMSAwIDIuNDU4IDEuMDggMi40ODYgMi40OTlDMTcgMTUuODg3IDE2LjAzNSAxNyAxNC40ODUgMTd6TTM2IDM2aC01di05LjA5OWMwLTIuMTk4LTEuMjI1LTMuNjk4LTMuMTkyLTMuNjk4LTEuNTAxIDAtMi4zMTMgMS4wMTItMi43MDcgMS45OS0uMTQ0LjM1LS4xMDEgMS4zMTgtLjEwMSAxLjgwN3Y5aC01VjE5aDV2Mi42MTZDMjUuNzIxIDIwLjUgMjYuODUgMTkgMjkuNzM4IDE5YzMuNTc4IDAgNi4yNjEgMi4yNSA2LjI2MSA3LjI3NEwzNiAzNnoiIGZpbGw9IiNGRkYiLz48L3N2Zz4='); }
38 .social-icon--twitter { background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0OCA0OCIgY2xpcC1ydWxlPSJldmVub2RkIj48cGF0aCBkPSJNMzggNDJIMTBhNCA0IDAgMCAxLTQtNFYxMGE0IDQgMCAwIDEgNC00aDI4YTQgNCAwIDAgMSA0IDR2MjhhNCA0IDAgMCAxLTQgNHoiIGZpbGwtcnVsZT0iZXZlbm9kZCIgZmlsbD0iIzIxMjEyMSIvPjxnIGZpbGw9IiNmZmYiPjxwYXRoIGQ9Ik0zNC4yNTcgMzRIMjcuODJMMTMuODI5IDE0aDYuNDM3em0tNS42Ny0xLjY5NmgyLjU2M0wxOS40OTkgMTUuNjk2aC0yLjU2M3oiLz48cGF0aCBkPSJNMTUuODY2IDM0bDcuMjAzLTguMzQ0LS45NDItMS4yNDlMMTMuODIzIDM0em04LjU4NC0xMi4yNzlsLjkwNSAxLjI4OUwzMy4xMzYgMTRoLTJ6Ii8+PC9nPjwvc3ZnPg=='); }
39 .social-icon--instagram {
40 --svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M11.999 7.377a4.623 4.623 0 1 0 0 9.248a4.623 4.623 0 0 0 0-9.248m0 7.627a3.004 3.004 0 1 1 0-6.008a3.004 3.004 0 0 1 0 6.008'/%3E%3Ccircle cx='16.806' cy='7.207' r='1.078' fill='%23000'/%3E%3Cpath fill='%23000' d='M20.533 6.111A4.605 4.605 0 0 0 17.9 3.479a6.606 6.606 0 0 0-2.186-.42c-.963-.042-1.268-.054-3.71-.054s-2.755 0-3.71.054a6.554 6.554 0 0 0-2.184.42a4.6 4.6 0 0 0-2.633 2.632a6.585 6.585 0 0 0-.419 2.186c-.043.962-.056 1.267-.056 3.71c0 2.442 0 2.753.056 3.71c.015.748.156 1.486.419 2.187a4.61 4.61 0 0 0 2.634 2.632a6.584 6.584 0 0 0 2.185.45c.963.042 1.268.055 3.71.055s2.755 0 3.71-.055a6.615 6.615 0 0 0 2.186-.419a4.613 4.613 0 0 0 2.633-2.633c.263-.7.404-1.438.419-2.186c.043-.962.056-1.267.056-3.71s0-2.753-.056-3.71a6.581 6.581 0 0 0-.421-2.217m-1.218 9.532a5.043 5.043 0 0 1-.311 1.688a2.987 2.987 0 0 1-1.712 1.711a4.985 4.985 0 0 1-1.67.311c-.95.044-1.218.055-3.654.055c-2.438 0-2.687 0-3.655-.055a4.96 4.96 0 0 1-1.669-.311a2.985 2.985 0 0 1-1.719-1.711a5.08 5.08 0 0 1-.311-1.669c-.043-.95-.053-1.218-.053-3.654c0-2.437 0-2.686.053-3.655a5.038 5.038 0 0 1 .311-1.687c.305-.789.93-1.41 1.719-1.712a5.01 5.01 0 0 1 1.669-.311c.951-.043 1.218-.055 3.655-.055s2.687 0 3.654.055a4.96 4.96 0 0 1 1.67.311a2.991 2.991 0 0 1 1.712 1.712a5.08 5.08 0 0 1 .311 1.669c.043.951.054 1.218.054 3.655c0 2.436 0 2.698-.043 3.654z'/%3E%3C/svg%3E");
41 background-color: currentColor;
42 -webkit-mask-image: var(--svg);
43 -webkit-mask-size: 100% 100%;
44 }
45</style>
46
47<div class="psp-date-title--space-between mb-5">
48 <div class="psp-date-title">
49 ${publicationDate} | Horário: ${formattedTime}
50 </div>
51 <div style="display: flex; gap: 16px;align-items:center;">
52 <span>Compartilhe:</span>
53 <a class="mt-n1" target="_blank" href="https://api.whatsapp.com/send?text=${themeDisplay.getPortalURL() + themeDisplay.getURLCurrent()}">
54<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="20px" height="20px"><path fill="#EC6608" fill-rule="evenodd" d="M 24.503906 7.503906 C 22.246094 5.246094 19.246094 4 16.050781 4 C 9.464844 4 4.101563 9.359375 4.101563 15.945313 C 4.097656 18.050781 4.648438 20.105469 5.695313 21.917969 L 4 28.109375 L 10.335938 26.445313 C 12.078125 27.398438 14.046875 27.898438 16.046875 27.902344 L 16.050781 27.902344 C 22.636719 27.902344 27.996094 22.542969 28 15.953125 C 28 12.761719 26.757813 9.761719 24.503906 7.503906 Z M 16.050781 25.882813 L 16.046875 25.882813 C 14.265625 25.882813 12.515625 25.402344 10.992188 24.5 L 10.628906 24.285156 L 6.867188 25.269531 L 7.871094 21.605469 L 7.636719 21.230469 C 6.640625 19.648438 6.117188 17.820313 6.117188 15.945313 C 6.117188 10.472656 10.574219 6.019531 16.054688 6.019531 C 18.707031 6.019531 21.199219 7.054688 23.074219 8.929688 C 24.949219 10.808594 25.980469 13.300781 25.980469 15.953125 C 25.980469 21.429688 21.523438 25.882813 16.050781 25.882813 Z M 21.496094 18.445313 C 21.199219 18.296875 19.730469 17.574219 19.457031 17.476563 C 19.183594 17.375 18.984375 17.328125 18.785156 17.625 C 18.585938 17.925781 18.015625 18.597656 17.839844 18.796875 C 17.667969 18.992188 17.492188 19.019531 17.195313 18.871094 C 16.894531 18.722656 15.933594 18.40625 14.792969 17.386719 C 13.90625 16.597656 13.304688 15.617188 13.132813 15.320313 C 12.957031 15.019531 13.113281 14.859375 13.261719 14.710938 C 13.398438 14.578125 13.5625 14.363281 13.710938 14.1875 C 13.859375 14.015625 13.910156 13.890625 14.011719 13.691406 C 14.109375 13.492188 14.058594 13.316406 13.984375 13.167969 C 13.910156 13.019531 13.3125 11.546875 13.0625 10.949219 C 12.820313 10.367188 12.574219 10.449219 12.390625 10.4375 C 12.21875 10.429688 12.019531 10.429688 11.820313 10.429688 C 11.621094 10.429688 11.296875 10.503906 11.023438 10.804688 C 10.75 11.101563 9.980469 11.824219 9.980469 13.292969 C 9.980469 14.761719 11.050781 16.183594 11.199219 16.382813 C 11.347656 16.578125 13.304688 19.59375 16.300781 20.886719 C 17.011719 21.195313 17.566406 21.378906 18 21.515625 C 18.714844 21.742188 19.367188 21.710938 19.882813 21.636719 C 20.457031 21.550781 21.648438 20.914063 21.898438 20.214844 C 22.144531 19.519531 22.144531 18.921875 22.070313 18.796875 C 21.996094 18.671875 21.796875 18.597656 21.496094 18.445313 Z"/></svg></a>
55 <a target="_blank" href="https://www.facebook.com/sharer/sharer.php?u=${themeDisplay.getPortalURL() + themeDisplay.getURLCurrent()}"><i class="psp-icon-facebook"></i></a>
56 <a target="_blank" href="https://twitter.com/intent/tweet?url=${themeDisplay.getPortalURL() + themeDisplay.getURLCurrent()}"><svg class="lexicon-icon lexicon-icon-twitter-x" role="presentation" viewBox="0 0 512 512">
57 <use xlink:href="/o/dialect-theme/images/clay/icons.svg#twitter-x"></use>
58 </svg></a>
59 <a target="_blank" href="https://www.linkedin.com/shareArticle?mini=true&url=${themeDisplay.getPortalURL() + themeDisplay.getURLCurrent()}"><i class="psp-icon-linkedin"></i></a>
60 </div>
61</div>
62
63<p class="psp-news-title mb-2">
64 ${title}
65</p>
66
67<#if (description.getData())??>
68 <div class="psp-news-description mb-5">${description.getData()}</div>
69</#if>
70
71<#if (subtitle.getData())??>
72 <div class="psp-news-description mb-5">${subtitle.getData()}</div>
73</#if>
74
75<#-- Apenas renderiza a imagem principal se ela existir (Sem Fallback) -->
76<#if (image.getData())?? && image.getData() != "">
77 <img class="mb-4" alt="${image.getAttribute('alt')}" data-fileentryid="${image.getAttribute('fileEntryId')}" src="${image.getData()}" loading="lazy" decoding="async" />
78</#if>
79
80<#-- ========================================== -->
81<#-- LÓGICA DO SLIDER ANTES/DEPOIS -->
82<#-- ========================================== -->
83
84<#assign conteudoFinal = (content.getData())!"" />
85
86<#-- O servidor só processa o HTML/CSS se a tag for encontrada no texto -->
87<#if conteudoFinal?contains("[[antes/depois]]")>
88 <#-- Mantendo fallback apenas para o Slider -->
89 <#assign fallbackImgAntes = "https://placehold.co/800x500/eeeeee/999999?text=Sem+Imagem+Antes" />
90 <#assign fallbackImgDepois = "https://placehold.co/800x500/cccccc/666666?text=Sem+Imagem+Depois" />
91
92 <#assign imgAntes = image_before.getData()!fallbackImgAntes />
93 <#if imgAntes == ""><#assign imgAntes = fallbackImgAntes /></#if>
94
95 <#assign imgDepois = image_after.getData()!fallbackImgDepois />
96 <#if imgDepois == ""><#assign imgDepois = fallbackImgDepois /></#if>
97
98 <#assign sliderHtml>
99 <div class="cx-slider-wrapper">
100 <style>
101 .cx-slider-container { --pos: 50%; position: relative; width: 100%; max-width: 800px; margin: 2rem auto; border-radius: 12px; overflow: hidden; box-shadow: 0 10px 30px rgba(0,0,0,0.15); display: flex; }
102 .cx-img-panel { width: 100%; display: flex; }
103 .cx-img-panel img { width: 100%; height: auto; object-fit: cover; pointer-events: none; display: block; }
104 .cx-img-before { position: absolute; inset: 0; clip-path: polygon(0 0, var(--pos) 0, var(--pos) 100%, 0 100%); }
105 .cx-label { position: absolute; top: 20px; padding: 6px 14px; background: rgba(0,0,0,0.6); color: #fff; border-radius: 20px; font-family: sans-serif; font-size: 13px; font-weight: bold; pointer-events: none; z-index: 5; }
106 .cx-label-before { left: 20px; } .cx-label-after { right: 20px; }
107 .cx-slider { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; z-index: 10; cursor: ew-resize; margin: 0; }
108 .cx-handle { position: absolute; top: 0; bottom: 0; left: var(--pos); width: 4px; background: #fff; transform: translateX(-50%); pointer-events: none; z-index: 8; box-shadow: 0 0 10px rgba(0,0,0,0.4); }
109 .cx-handle-btn { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 40px; height: 40px; background: #fff; border-radius: 50%; display: flex; align-items: center; justify-content: center; box-shadow: 0 4px 10px rgba(0,0,0,0.3); }
110 .cx-handle-btn svg { width: 24px; height: 24px; color: #333; }
111 </style>
112 <div class="cx-slider-container" style="--pos: 50%;">
113 <div class="cx-img-panel cx-img-after">
114 <img src="${imgDepois}" alt="Imagem Depois" loading="lazy" decoding="async" />
115 <span class="cx-label cx-label-after">Depois</span>
116 </div>
117 <div class="cx-img-panel cx-img-before">
118 <img src="${imgAntes}" alt="Imagem Antes" loading="lazy" decoding="async" />
119 <span class="cx-label cx-label-before">Antes</span>
120 </div>
121 <input type="range" min="0" max="100" value="50" class="cx-slider" aria-label="Controlador de comparação antes e depois" oninput="this.parentElement.style.setProperty('--pos', this.value + '%')">
122 <div class="cx-handle"><div class="cx-handle-btn"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 18l-6-6 6-6M9 18l6-6-6-6" /></svg></div></div>
123 </div>
124 </div>
125 </#assign>
126
127 <#assign conteudoFinal = conteudoFinal?replace("<p>[[antes/depois]]</p>", sliderHtml) />
128 <#assign conteudoFinal = conteudoFinal?replace("[[antes/depois]]", sliderHtml) />
129</#if>
130
131<div class="psp-news-text">
132 ${conteudoFinal}
133</div>
134
135<#assign articleId = .vars["reserved-article-id"].data />
136
137<div class="psp-section-title mt-6 mb-4 d-none" data-article-id="${articleId}">
138 <div class="psp-section-title__main mr-5">
139 <div class="psp-section-title__icon text-7 mr-5"><i class="material-icon">collections</i></div>
140 <div class="psp-section-title__text text-6 font-weight-semi-bold">
141 <div>Galeria de imagens</div>
142 </div>
143 </div>
144 <div class="psp-section-title__divider d-none d-sm-block"></div>
145</div>
146
147<div class="pswp-gallery psp-gallery-${randomNamespace}" data-input-gallery></div>
148
149<script>
150 (function() {
151 const articleId = document.querySelector('[data-article-id]').getAttribute('data-article-id');
152 const groupId = themeDisplay.getSiteGroupId();
153 const galleryContainer = document.querySelector('[data-input-gallery]');
154
155 async function fetchArticle() {
156 try {
157 const article = await fetch(`/o/headless-delivery/v1.0/sites/${groupId}/structured-contents/by-key/${articleId}`);
158 if (!article.ok) throw new Error("Erro ao buscar a notícia");
159 const data = await article.json();
160 renderArticle(data);
161 } catch (error) {
162 console.error("[Galeria] Falha ao carregar artigo base:", error);
163 }
164 }
165
166 async function fetchDoc(id) {
167 try {
168 const doc = await fetch('/o/headless-delivery/v1.0/documents/' + id);
169 if (!doc.ok) return null;
170 return await doc.json();
171 } catch (error) {
172 console.error("[Galeria] Falha ao carregar a imagem com ID:", id);
173 return null;
174 }
175 }
176
177 async function renderArticle(data) {
178 if (!data.relatedContents || data.relatedContents.length === 0) return;
179
180 document.querySelector(`[data-article-id="${articleId}"]`).classList.remove('d-none');
181
182 const ids = data.relatedContents.map(object => object.id);
183
184 // Fetching paralelo de alta performance
185 const docs = await Promise.all(ids.map(id => fetchDoc(id)));
186
187 const fragment = document.createDocumentFragment();
188 docs.forEach(doc => {
189 if (doc) renderImage(doc, fragment);
190 });
191
192 galleryContainer.appendChild(fragment);
193 initLightbox();
194 }
195
196 function removeStringDownload(stringToRemove){
197 return stringToRemove.replace(/(\?|&)download=true/g, '$1download=false');
198 }
199
200 function renderImage(img, container) {
201 if (!img.contentUrl) return;
202
203 const imgURL = removeStringDownload(img.contentUrl);
204
205 const galleryLink = document.createElement('a');
206 galleryLink.setAttribute('title', 'Link para a imagem da galeria');
207 galleryLink.setAttribute('href', imgURL);
208 galleryLink.setAttribute('data-pswp-width', '1200');
209 galleryLink.setAttribute('data-pswp-height', '800');
210 galleryLink.setAttribute('target', '_blank');
211
212 const picture = document.createElement('picture');
213 const smallerMedia = document.createElement('source');
214 smallerMedia.setAttribute('media', '(max-width:300px)');
215 smallerMedia.setAttribute('srcset', img.contentUrl);
216
217 const biggerMedia = document.createElement('source');
218 biggerMedia.setAttribute('media', '(max-width:1000px) and (min-width:300px)');
219 biggerMedia.setAttribute('srcset', img.contentUrl);
220
221 const imgElement = document.createElement('img');
222 imgElement.setAttribute('alt', 'Imagem da galeria');
223 imgElement.src = imgURL;
224 imgElement.setAttribute('loading', 'lazy');
225 imgElement.setAttribute('decoding', 'async');
226
227 picture.append(smallerMedia, biggerMedia, imgElement);
228 galleryLink.appendChild(picture);
229
230 const captionContentDiv = document.createElement('div');
231 captionContentDiv.classList.add('hidden-caption-content');
232
233 if (Array.isArray(img.customFields)) {
234 img.customFields.forEach(cf => {
235 if (cf.name === "Descrição Imagem" && cf.customValue.data !== "") {
236 captionContentDiv.innerHTML += `<span>${cf.customValue.data}</span><br>`;
237 }
238 if (cf.name === "Crédito Imagem" && cf.customValue.data !== "") {
239 captionContentDiv.innerHTML += `<span>Fotos de: ${cf.customValue.data}</span>`;
240 }
241 });
242 }
243
244 galleryLink.appendChild(captionContentDiv);
245 container.appendChild(galleryLink);
246 }
247
248 function initLightbox() {
249 var galleryImageElem = document.querySelector(".psp-gallery-" + "${randomNamespace}");
250
251 if (galleryImageElem && typeof PSP !== 'undefined') {
252 const lightbox = new PSP.vendors.PhotoSwipeLightbox({
253 gallery: '.psp-gallery-' + "${randomNamespace}",
254 children: 'a',
255 pswpModule: () => import('https://unpkg.com/photoswipe'),
256 });
257
258 lightbox.on('uiRegister', function() {
259 lightbox.pswp.ui.registerElement({
260 name: 'custom-caption',
261 order: 9,
262 isButton: false,
263 appendTo: 'root',
264 html: 'Caption text',
265 onInit: (el, pswp) => {
266 lightbox.pswp.on('change', () => {
267 const currSlideElement = lightbox.pswp.currSlide.data.element;
268 let captionHTML = '';
269 if (currSlideElement) {
270 const hiddenCaption = currSlideElement.querySelector('.hidden-caption-content');
271 captionHTML = hiddenCaption ? hiddenCaption.innerHTML : currSlideElement.querySelector('img').getAttribute('alt');
272 }
273 el.classList.toggle('d-none', !captionHTML.trim());
274 el.innerHTML = captionHTML || '';
275 });
276 }
277 });
278 });
279 lightbox.init();
280 }
281 }
282
283 fetchArticle();
284 })();
285</script>
HAND TALK
Clique neste componente para ter acesso as configurações do plugin Hand Talk