github.com/GoogleContainerTools/skaffold/v2@v2.13.2/docs-v2/content/en/docs/references/yaml/main.js (about) 1 import { html, render } from 'https://unpkg.com/lit-html@1.1.2/lit-html.js'; 2 import { unsafeHTML } from 'https://unpkg.com/lit-html@1.1.2/directives/unsafe-html.js'; 3 4 var version; 5 let latest; 6 7 class YamlLink { 8 constructor(url, label) { 9 this.url = `#${url}`; 10 this.label = label 11 } 12 13 render() { 14 return html`<a class="yaml-link" href="${this.url}">${this.label}</a>`; 15 } 16 } 17 18 (async function() { 19 const versionParam = "?version="; 20 const index = window.location.href.indexOf(versionParam); 21 const table = document.getElementById('table'); 22 const versionInfo = document.getElementById('version-info') 23 24 latest = table.attributes['latest'].value.trim(); 25 if (index === -1) { 26 version = table.attributes['data-version'].value.trim(); 27 version = version.replace('skaffold/', ''); 28 } else { 29 version = window.location.href.substr(index + versionParam.length); 30 table.attributes['data-version'].value = 'skaffold/' + version; 31 } 32 33 const versionInfoResponse = await fetch(`/schemas/version-mappings/${version}-version.json`); 34 if (versionInfoResponse.ok) { 35 const versionInfoJson = await versionInfoResponse.json(); 36 render(html` 37 <strong>Important:</strong> To use this schema, you need Skaffold version ${versionInfoJson.binVersion} or later. 38 <a href="${versionInfoJson.releaseNoteLink}">Release Notes</a> 39 `, versionInfo) 40 } 41 42 const response = await fetch(`/schemas/${version}.json`); 43 const json = await response.json(); 44 45 render(html` 46 ${template(json.definitions, undefined, json.anyOf[0].$ref, 0, "", [])} 47 `, table); 48 49 if (location.hash) { 50 table.querySelector(location.hash).scrollIntoView(); 51 } 52 })(); 53 54 function* template(definitions, parentDefinition, ref, ident, parent, parentLinks) { 55 const name = ref.replace('#/definitions/', ''); 56 const allProperties = []; 57 const seen = {}; 58 59 const properties = definitions[name].properties; 60 for (const key of (definitions[name].preferredOrder || [])) { 61 allProperties.push([key, properties[key]]); 62 seen[key] = true; 63 } 64 65 const anyOfs = definitions[name].anyOf; 66 for (const anyOf of (anyOfs || [])) { 67 for (const key of (anyOf.preferredOrder || [])) { 68 if (seen[key]) continue; 69 70 allProperties.push([key, anyOf.properties[key]]); 71 seen[key] = true; 72 } 73 } 74 75 let index = -1; 76 for (let [key, definition] of allProperties) { 77 const path = parent.length == 0 ? key : `${parent}-${key}`; 78 const propetyLabel = (definition.items && definition.items.$ref) ? `${key}[]`: `${key}`; 79 const yamlLink = new YamlLink(path, propetyLabel); 80 const pathLinks = [...parentLinks, yamlLink] 81 const renderedPath = getPathLinkList(pathLinks); 82 index++; 83 84 // Key 85 let required = definitions[name].required && definitions[name].required.includes(key); 86 let keyClass = required ? 'key required' : 'key'; 87 88 // Value 89 let value = definition.default; 90 if (key === 'apiVersion') { 91 value = `skaffold/${version}`; 92 } else if (definition.examples && definition.examples.length > 0) { 93 value = definition.examples[0]; 94 } 95 let valueClass = definition.examples ? 'example' : 'value'; 96 97 // Description 98 let desc = definition['x-intellij-html-description']; 99 if (!desc) { 100 desc = "" 101 } 102 103 // Don't duplicate definitions of top level sections such as build, test, deploy and portForward. 104 if ((name === 'Profile') && definitions['SkaffoldConfig'].properties[key]) { 105 value = '{}'; 106 yield html` 107 <tr> 108 <td> 109 <span class="${keyClass}" style="margin-left: ${ident * 20}px">${anchor(path, key)}:${tooltip(renderedPath)}</span> 110 <span class="${valueClass}">${value}</span> 111 </td> 112 <td><span class="comment"># </span></td> 113 <td><span class="comment">${unsafeHTML(desc)}</span></td> 114 </tr> 115 `; 116 continue; 117 } 118 119 if (definition.$ref) { 120 // Check if the referenced description is a final one 121 const refName = definition.$ref.replace('#/definitions/', ''); 122 if (desc === "" && definitions[refName]['x-intellij-html-description']) { 123 desc = definitions[refName]['x-intellij-html-description']; 124 } 125 if (!definitions[refName].properties && !definitions[refName].anyOf) { 126 value = '{}'; 127 } 128 129 yield html` 130 <tr class="top"> 131 <td> 132 <span class="${keyClass}" style="margin-left: ${ident * 20}px">${anchor(path, key)}:${tooltip(renderedPath)}</span> 133 <span class="${valueClass}">${value}</span> 134 </td> 135 <td class="comment"># </td> 136 <td class="comment">${unsafeHTML(desc)}</td> 137 </tr> 138 `; 139 } else if (definition.items && definition.items.$ref) { 140 const refName = definition.items.$ref.replace('#/definitions/', ''); 141 if (desc === "" && definitions[refName]['x-intellij-html-description']) { 142 desc = definitions[refName]['x-intellij-html-description']; 143 } 144 yield html` 145 <tr class="top"> 146 <td> 147 <span class="${keyClass}" style="margin-left: ${ident * 20}px">${anchor(path, key)}:${tooltip(renderedPath)}</span> 148 <span class="${valueClass}">${value}</span> 149 </td> 150 <td class="comment"># </td> 151 <td class="comment">${unsafeHTML(desc)}</td> 152 </tr> 153 `; 154 } else if (parentDefinition && (parentDefinition.type === 'array') && (index === 0)) { 155 yield html` 156 <tr> 157 <td> 158 159 <span class="${keyClass}" style="margin-left: ${(ident - 1) * 20}px">- ${anchor(path, key)}:${tooltip(renderedPath)}</span> 160 <span class="${valueClass}">${value}</span> 161 </td> 162 <td class="comment"># </td> 163 <td class="comment">${unsafeHTML(desc)}</td> 164 </tr> 165 `; 166 } else if ((definition.type === 'array') && value && (value !== '[]')) { 167 // Parse value to json array 168 const values = JSON.parse(value); 169 170 yield html` 171 <tr> 172 <td> 173 174 <span class="${keyClass}" style="margin-left: ${ident * 20}px">${anchor(path, key)}:${tooltip(renderedPath)}</span> 175 </td> 176 <td class="comment"># </td> 177 <td class="comment" rowspan="${1 + values.length}"> 178 ${unsafeHTML(desc)} 179 </td> 180 </tr> 181 `; 182 183 for (const v of values) { 184 yield html` 185 <tr> 186 <td> 187 <span class="key" style="margin-left: ${ident * 20}px">- <span class="${valueClass}">${JSON.stringify(v)}</span></span> 188 </td> 189 <td class="comment"># </td> 190 </tr> 191 `; 192 } 193 } else if (definition.type === 'object' && value && value !== '{}') { 194 // Parse value to json object 195 const values = JSON.parse(value); 196 197 yield html` 198 <tr> 199 <td> 200 <span class="${keyClass}" style="margin-left: ${ident * 20}px">${anchor(path, key)}:${tooltip(renderedPath)}</span> 201 </td> 202 <td class="comment"># </td> 203 <td class="comment" rowspan="${1 + Object.keys(values).length}"> 204 ${unsafeHTML(desc)} 205 </td> 206 </tr> 207 `; 208 209 for (const k in values) { 210 if (!values.hasOwnProperty(k)) continue; 211 const v = values[k]; 212 213 yield html` 214 <tr> 215 <td> 216 217 <span class="key" style="margin-left: ${(ident + 1) * 20}px">${k}:${tooltip(renderedPath)}<span class="${valueClass}">${v}</span> 218 </span> 219 </td> 220 <td class="comment"># </td> 221 </tr> 222 `; 223 } 224 } else { 225 yield html` 226 <tr> 227 <td> 228 <span class="${keyClass}" style="margin-left: ${ident * 20}px">${anchor(path, key)}:${tooltip(renderedPath)}</span> 229 <span class="${valueClass}">${value}</span> 230 <span class="${keyClass}">${getLatest(key === 'apiVersion' && latest === value)}</span> 231 </td> 232 <td class="comment"># </td> 233 <td class="comment">${unsafeHTML(desc)}</td> 234 </tr> 235 `; 236 } 237 238 // This definition references another definition 239 if (definition.$ref) { 240 yield html` 241 ${template(definitions, definition, definition.$ref, ident + 1, path, pathLinks)} 242 `; 243 } 244 245 // This definition is an array 246 if (definition.items && definition.items.$ref) { 247 // don't infinitely recurse into nested tagger components 248 if (definition.items.$ref === "#/definitions/TaggerComponent") { 249 yield html ``; 250 } else { 251 yield html` 252 ${template(definitions, definition, definition.items.$ref, ident + 1, path, pathLinks)} 253 `; 254 } 255 } 256 } 257 } 258 259 function getLatest(isLatest) { 260 return isLatest ? "latest" : ""; 261 } 262 263 function anchor(path, label) { 264 return html`<a class="anchor" id="${path}"></a><a class="key stooltip__anchor" href="#${path}">${label}</a>`; 265 } 266 267 function tooltip(content) { 268 return html`<span class="stooltip"><span class="stooltip__content">${content}<span class="stooltip__icon"><i class="fas fa-arrow-left"></i></span></span>`; 269 } 270 271 function getPathLinkList(yamlLinks) { 272 return html`${joinTemplates(yamlLinks.map((yamlLink) => yamlLink.render()), html`<span class="yaml-link__separator">.</span>`)}`; 273 } 274 275 function joinTemplates(templates=[html``], separator=html` `) { 276 const joinedTemplates = []; 277 278 for (const template of templates) { 279 joinedTemplates.push(template); 280 joinedTemplates.push(separator); 281 } 282 joinedTemplates.pop(); 283 284 return joinedTemplates; 285 }