{"id":2389,"date":"2025-09-16T00:59:30","date_gmt":"2025-09-15T22:59:30","guid":{"rendered":"https:\/\/davidka.net\/ru\/?p=2389"},"modified":"2025-09-22T02:42:47","modified_gmt":"2025-09-22T00:42:47","slug":"shadow-dom","status":"publish","type":"post","link":"https:\/\/it.davidka.net\/it\/shadow-dom\/","title":{"rendered":"Shadow DOM \u2014 \u201cDOM dentro il DOM\u201d"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Certamente, ecco la traduzione in italiano:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Shadow DOM \u2014 \u201cDOM dentro al DOM\u201d<\/strong><\/p>\n\n\n\n<div id=\"rtoc-mokuji-wrapper\" class=\"rtoc-mokuji-content frame2 preset1 animation-fade rtoc_open default\" data-id=\"2389\" data-theme=\"Neve - Davidka\">\n\t\t\t<div id=\"rtoc-mokuji-title\" class=\"rtoc_btn_none rtoc_left\">\n\t\t\t\n\t\t\t<span>In Questo Articolo<\/span>\n\t\t\t<\/div><ul class=\"rtoc-mokuji mokuji_ul level-2\"><li class=\"rtoc-item\"><a href=\"#rtoc-1\">Shadow DOM \u2014 \u201cDOM dentro al DOM\u201d<\/a><ul class=\"rtoc-mokuji mokuji_none level-3\"><li class=\"rtoc-item\"><a href=\"#rtoc-2\">Creazione dello Shadow DOM<\/a><ul class=\"rtoc-mokuji mokuji_none level-3\"><li class=\"rtoc-item\"><a href=\"#rtoc-3\">Incapsulamento: protezione da JavaScript e CSS<\/a><\/li><li class=\"rtoc-item\"><a href=\"#rtoc-4\">Styling all&#8217;interno dello Shadow DOM<\/a><\/li><\/ul><\/li><\/ul><\/li><\/ol><\/div><h3 id=\"rtoc-1\"  class=\"wp-block-heading\">Shadow DOM \u2014 \u201cDOM dentro al DOM\u201d<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Il DOM (Document Object Model) \u00e8 un&#8217;interfaccia di programmazione (API) per il codice di una pagina che la rappresenta come una struttura ad albero di oggetti.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ogni elemento HTML (ad esempio, <code class=\"\" data-line=\"\">&lt;p&gt;<\/code>, <code class=\"\" data-line=\"\">&lt;div&gt;<\/code>, <code class=\"\" data-line=\"\">&lt;img&gt;<\/code>), ogni attributo e ogni pezzo di testo \u00e8 un \u201cnodo\u201d separato in questo albero. Utilizzando JavaScript, possiamo interagire con questi nodi per modificare dinamicamente la pagina: cambiare testo, aggiungere stili, creare nuovi elementi o rimuovere quelli esistenti. In sostanza, il DOM \u00e8 un modello \u201cvivo\u201d del documento con cui il codice interagisce.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ma questa apertura ha un lato negativo. Quando creiamo un componente complesso e riutilizzabile (ad esempio, un lettore video personalizzato o un widget calendario), la sua struttura interna e i suoi stili diventano vulnerabili. Gli stili CSS della pagina principale possono accidentalmente \u201cpenetrare\u201d nel componente e romperne l&#8217;aspetto. Allo stesso modo, il codice JavaScript della pagina pu\u00f2 modificare involontariamente gli elementi interni del componente, interrompendone la logica.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Per risolvere questo problema, esiste lo <strong>Shadow DOM<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In sostanza, lo Shadow DOM \u00e8 un <strong>\u201cDOM dentro al DOM\u201d<\/strong>. \u00c8 un albero di elementi nascosto, collegato a un normale elemento della pagina (chiamato \u201chost\u201d o \u201cospite\u201d), ma isolato dal DOM principale. Permette allo sviluppatore di creare un confine sigillato attorno alla struttura interna di un componente, proteggendolo dal mondo esterno.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Lo Shadow DOM consente di collegare alberi DOM nascosti a elementi nell&#8217;albero DOM regolare. Questo albero \u201combra\u201d inizia con una <strong>radice shadow<\/strong> (shadow root), sotto la quale \u00e8 possibile aggiungere qualsiasi elemento, proprio come nel DOM normale.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ci sono diversi termini chiave relativi allo Shadow DOM che dovresti conoscere. Lo <strong>Shadow host<\/strong> (o ospite) \u00e8 un normale nodo del DOM a cui \u00e8 collegato uno Shadow DOM. L&#8217;<strong>albero shadow<\/strong> (Shadow tree) \u00e8 l&#8217;albero del DOM all&#8217;interno dello Shadow DOM. Il <strong>confine shadow<\/strong> (Shadow boundary) \u00e8 il punto in cui finisce lo Shadow DOM e inizia il DOM regolare. Infine, la <strong>radice shadow<\/strong> (Shadow root) \u00e8 il nodo radice dell&#8217;albero shadow.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"..\/..\/assets\/shadow_dom\/file.png\" alt=\"DOM\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">\u00c8 possibile manipolare i nodi all&#8217;interno dello Shadow DOM come si fa con i nodi normali. La differenza \u00e8 che nessun codice all&#8217;interno dello Shadow DOM pu\u00f2 influenzare nulla al di fuori di esso, garantendo un incapsulamento affidabile.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Prima che lo Shadow DOM diventasse disponibile per gli sviluppatori web, i browser lo utilizzavano gi\u00e0 per incapsulare la struttura interna degli elementi standard. Ad esempio, l&#8217;elemento <code class=\"\" data-line=\"\">&lt;video&gt;<\/code> con i controlli. Tutto ci\u00f2 che vedi nel DOM \u00e8 il tag <code class=\"\" data-line=\"\">&lt;video&gt;<\/code>, ma esso contiene diversi pulsanti e altri controlli all&#8217;interno del suo Shadow DOM.<\/p>\n\n\n\n<h4 id=\"rtoc-2\"  class=\"wp-block-heading\">Creazione dello Shadow DOM<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Lo Shadow DOM pu\u00f2 essere creato sia in modo imperativo tramite JavaScript, sia in modo dichiarativo direttamente nell&#8217;HTML.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">In modo imperativo con JavaScript<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">Questo metodo \u00e8 perfetto per le applicazioni renderizzate dal client. Selezioniamo l&#8217;elemento host e invochiamo su di esso il metodo <code class=\"\" data-line=\"\">attachShadow()<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\">&lt;!-- Markup HTML --&gt;\n&lt;div id=&quot;host&quot;&gt;&lt;\/div&gt;\n&lt;span&gt;Non sono nello Shadow DOM&lt;\/span&gt;<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\">\/\/ Trova l&#039;host e collega lo Shadow DOM\nconst host = document.querySelector(&quot;#host&quot;);\nconst shadow = host.attachShadow({ mode: &quot;open&quot; });\n\n\/\/ Crea e aggiungi elementi all&#039;albero shadow\nconst span = document.createElement(&quot;span&quot;);\nspan.textContent = &quot;Sono nello Shadow DOM&quot;;\nshadow.appendChild(span);<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Il risultato sulla pagina sar\u00e0 simile a questo:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">Sono nello Shadow DOM<br>Non sono nello Shadow DOM<\/p>\n<\/blockquote>\n\n\n\n<h5 class=\"wp-block-heading\">In modo dichiarativo con HTML<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">Per le applicazioni in cui il rendering lato server \u00e8 importante, \u00e8 possibile definire lo Shadow DOM in modo dichiarativo utilizzando un elemento <code class=\"\" data-line=\"\">&lt;template&gt;<\/code> con l&#8217;attributo <code class=\"\" data-line=\"\">shadowrootmode<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\">&lt;div id=&quot;host&quot;&gt;\n  &lt;template shadowrootmode=&quot;open&quot;&gt;\n    &lt;p&gt;Questo paragrafo \u00e8 all&#039;interno dello Shadow DOM.&lt;\/p&gt;\n    &lt;style&gt;\n      p { color: red; } \/* Questi stili saranno isolati *\/\n    &lt;\/style&gt;\n  &lt;\/template&gt;\n&lt;\/div&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Quando il browser elabora questo codice, crea automaticamente una radice shadow per il <code class=\"\" data-line=\"\">&lt;div&gt;<\/code> e inserisce il contenuto del <code class=\"\" data-line=\"\">&lt;template&gt;<\/code> al suo interno. Il tag <code class=\"\" data-line=\"\">&lt;template&gt;<\/code> stesso scompare dall&#8217;albero DOM principale.<\/p>\n\n\n\n<h4 id=\"rtoc-3\"  class=\"wp-block-heading\">Incapsulamento: protezione da JavaScript e CSS<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Il vantaggio principale dello Shadow DOM \u00e8 l&#8217;isolamento. Vediamo come funziona.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Incapsulamento di JavaScript<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">Aggiungiamo un pulsante che cerca di modificare tutti gli elementi <code class=\"\" data-line=\"\">&lt;span&gt;<\/code> sulla pagina.<\/p>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\">\/\/ ... Codice di creazione dello Shadow DOM ...\n\nconst upper = document.querySelector(&quot;#upper-button&quot;);\nupper.addEventListener(&quot;click&quot;, () =&gt; {\n  \/\/ Questo selettore cerca in tutto il documento\n  const spans = document.querySelectorAll(&quot;span&quot;);\n  for (const span of spans) {\n    span.textContent = span.textContent.toUpperCase();\n  }\n});<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Quando si fa clic sul pulsante, solo lo <code class=\"\" data-line=\"\">&lt;span&gt;<\/code> nel documento principale cambia. L&#8217;elemento all&#8217;interno dello Shadow DOM rimane invariato perch\u00e9 <code class=\"\" data-line=\"\">document.querySelectorAll()<\/code> non pu\u00f2 \u201cguardare\u201d oltre il confine dello shadow.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Accedere allo Shadow DOM: la propriet\u00e0 <code class=\"\" data-line=\"\">shadowRoot<\/code> e gli alberi nidificati<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">Quando chiamiamo <code class=\"\" data-line=\"\">host.attachShadow({ mode: &quot;open&quot; })<\/code>, creiamo uno Shadow DOM \u201caperto\u201d. Ci\u00f2 significa che possiamo accedere al suo contenuto dall&#8217;esterno tramite <code class=\"\" data-line=\"\">host.shadowRoot<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\">\/\/ Trova gli span solo all&#039;interno dell&#039;albero shadow di un host specifico\nconst spansInShadow = host.shadowRoot.querySelectorAll(&quot;span&quot;);<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Se si utilizza <code class=\"\" data-line=\"\">mode: &quot;closed&quot;<\/code>, <code class=\"\" data-line=\"\">host.shadowRoot<\/code> restituisce <code class=\"\" data-line=\"\">null<\/code>, e l&#8217;accesso esterno all&#8217;albero shadow \u00e8 bloccato. Non si tratta di un meccanismo di sicurezza rigoroso, ma piuttosto di una convenzione per gli sviluppatori che indica che le parti interne del componente non dovrebbero essere toccate.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Lavorare con alberi shadow nidificati<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In architetture di componenti complesse, un elemento personalizzato pu\u00f2 contenerne altri, ognuno con il proprio Shadow DOM. Per accedere a un elemento in un albero shadow profondamente nidificato, \u00e8 necessario attraversare ogni <code class=\"\" data-line=\"\">shadowRoot<\/code> in sequenza.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Una struttura di esempio potrebbe essere: un componente <code class=\"\" data-line=\"\">&lt;nmbrs-form&gt;<\/code> (il modulo principale), che al suo interno ha un <code class=\"\" data-line=\"\">&lt;div&gt;<\/code> contenente un <code class=\"\" data-line=\"\">&lt;nmbrs-button&gt;<\/code> (un pulsante personalizzato), e all&#8217;interno di questo <code class=\"\" data-line=\"\">&lt;nmbrs-button&gt;<\/code> si trova un vero e proprio elemento <code class=\"\" data-line=\"\">&lt;button&gt;<\/code> HTML.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Per accedere a questo pulsante dal contesto globale, il percorso \u00e8:<\/p>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\">\/\/ 1. Trova il componente radice nel documento principale\nconst formComponent = document.querySelector(&#039;nmbrs-form&#039;);\n\n\/\/ 2. Entra nel suo albero shadow\nconst shadowRoot1 = formComponent.shadowRoot;\n\n\/\/ 3. Trova il componente pulsante nidificato\nconst buttonComponent = shadowRoot1.querySelector(&#039;div div.btn-container nmbrs-button&#039;);\n\n\/\/ 4. Entra nell&#039;albero shadow di questo componente\nconst shadowRoot2 = buttonComponent.shadowRoot;\n\n\/\/ 5. Infine, trova l&#039;elemento pulsante\nconst finalButton = shadowRoot2.querySelector(&#039;button#button&#039;);<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Come una singola catena:<\/p>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\">const button = document.querySelector(&#039;nmbrs-form&#039;).shadowRoot\n                      .querySelector(&#039;div div.btn-container nmbrs-button&#039;).shadowRoot\n                      .querySelector(&#039;button#button&#039;);<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Questa lunga catena dimostra la potenza dell&#8217;incapsulamento: per raggiungere i dettagli interni, \u00e8 necessario attraversare esplicitamente ogni \u201cconfine\u201d. Questo rende il codice pi\u00f9 prevedibile e protegge i componenti da modifiche accidentali.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Incapsulamento di CSS<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">Gli stili definiti nella pagina principale non influenzano gli elementi all&#8217;interno dello Shadow DOM.<\/p>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\">\/* Questo stile si applica solo agli span nel documento principale *\/\nspan {\n  color: blue;\n  border: 1px solid black;\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Lo <code class=\"\" data-line=\"\">&lt;span&gt;<\/code> all&#8217;interno dell&#8217;albero shadow non ricever\u00e0 questi stili. Questo risolve il problema dei conflitti di stile accidentali.<\/p>\n\n\n\n<h4 id=\"rtoc-4\"  class=\"wp-block-heading\">Styling all&#8217;interno dello Shadow DOM<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Gli stili definiti all&#8217;interno dell&#8217;albero shadow, a loro volta, non influenzano la pagina principale. Ci sono due modi principali per aggiungerli.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">1. Fogli di stile costruibili (Constructable Stylesheets)<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">Questo metodo consente di creare un oggetto <code class=\"\" data-line=\"\">CSSStyleSheet<\/code> in JavaScript e di applicarlo a uno o pi\u00f9 alberi shadow. \u00c8 efficiente se si hanno stili condivisi per molti componenti.<\/p>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\">const sheet = new CSSStyleSheet();\nsheet.replaceSync(&quot;span { color: red; border: 2px dotted black; }&quot;);\n\nconst shadow = host.attachShadow({ mode: &quot;open&quot; });\n\/\/ Applica il foglio di stile alla radice shadow\nshadow.adoptedStyleSheets = &#091;sheet];<\/code><\/pre>\n\n\n\n<h5 class=\"wp-block-heading\">2. L&#8217;elemento <code class=\"\" data-line=\"\">&lt;style&gt;<\/code><\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">Un modo semplice e dichiarativo \u00e8 inserire un tag <code class=\"\" data-line=\"\">&lt;style&gt;<\/code> direttamente all&#8217;interno dell&#8217;albero shadow (spesso all&#8217;interno di un <code class=\"\" data-line=\"\">&lt;template&gt;<\/code>).<\/p>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\">&lt;template id=&quot;my-element&quot;&gt;\n  &lt;style&gt;\n    span {\n      color: red;\n      border: 2px dotted black;\n    }\n  &lt;\/style&gt;\n  &lt;span&gt;Sono nello Shadow DOM&lt;\/span&gt;\n&lt;\/template&gt;```\n\n#### Shadow DOM e Custom Elements: un&#039;accoppiata perfetta\n\nLa piena potenza dello Shadow DOM si rivela durante la creazione di **Custom Elements** (Elementi Personalizzati). Senza incapsulamento, sarebbero estremamente fragili.\n\nUn elemento personalizzato \u00e8 una classe che estende `HTMLElement`. Tipicamente, l&#039;elemento stesso agisce come host dello shadow, e la sua struttura interna viene creata all&#039;interno dell&#039;albero shadow.\n\nEsempio di un semplice componente `&lt;filled-circle&gt;`:<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">javascript<br>class FilledCircle extends HTMLElement {<br>connectedCallback() {<br>const shadow = this.attachShadow({ mode: &#8220;open&#8221; });<\/p>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\">\/\/ Crea l&#039;implementazione interna (es. un cerchio SVG)\nconst svg = document.createElementNS(&quot;http:\/\/www.w3.org\/2000\/svg&quot;, &quot;svg&quot;);\nconst circle = document.createElementNS(&quot;http:\/\/www.w3.org\/2000\/svg&quot;, &quot;circle&quot;);\ncircle.setAttribute(&quot;r&quot;, &quot;50&quot;);\ncircle.setAttribute(&quot;cx&quot;, &quot;50&quot;);\ncircle.setAttribute(&quot;cy&quot;, &quot;50&quot;);\n\/\/ Il colore proviene dall&#039;attributo dell&#039;host\ncircle.setAttribute(&quot;fill&quot;, this.getAttribute(&quot;color&quot;));\n\nsvg.appendChild(circle);\nshadow.appendChild(svg);<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">}<br>}<br>customElements.define(&#8220;filled-circle&#8221;, FilledCircle);<\/p>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\">Ora possiamo usarlo in HTML come un normale tag senza preoccuparci della sua struttura interna:<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">html<br><br><br>&#8220;`<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ognuno di questi componenti sar\u00e0 completamente incapsulato e protetto dalla pagina esterna.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Lo Shadow DOM permette di creare un \u201cDOM dentro il DOM\u201d, fornendo incapsulamento per la struttura interna e gli stili dei componenti. Questo protegge gli elementi personalizzati da interferenze esterne di JavaScript e CSS, garantisce un comportamento prevedibile, facilita l\u2019annidamento sicuro e rende i componenti complessi pi\u00f9 robusti e manutenibili. In combinazione con i Custom Elements, consente di costruire interfacce isolate, riutilizzabili e affidabili.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"neve_meta_sidebar":"","neve_meta_container":"","neve_meta_enable_content_width":"","neve_meta_content_width":0,"neve_meta_title_alignment":"","neve_meta_author_avatar":"","neve_post_elements_order":"","neve_meta_disable_header":"","neve_meta_disable_footer":"","neve_meta_disable_title":"","_themeisle_gutenberg_block_has_review":false,"footnotes":""},"categories":[1],"tags":[867],"class_list":["post-2389","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-tag-dom"],"acf":[],"_links":{"self":[{"href":"https:\/\/it.davidka.net\/it\/wp-json\/wp\/v2\/posts\/2389","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/it.davidka.net\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/it.davidka.net\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/it.davidka.net\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/it.davidka.net\/it\/wp-json\/wp\/v2\/comments?post=2389"}],"version-history":[{"count":0,"href":"https:\/\/it.davidka.net\/it\/wp-json\/wp\/v2\/posts\/2389\/revisions"}],"wp:attachment":[{"href":"https:\/\/it.davidka.net\/it\/wp-json\/wp\/v2\/media?parent=2389"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/it.davidka.net\/it\/wp-json\/wp\/v2\/categories?post=2389"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/it.davidka.net\/it\/wp-json\/wp\/v2\/tags?post=2389"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}