document.addEventListener('DOMContentLoaded', function () { // detect current environment (local, dev, ppe, stage/qa, prod) window.MsrcEnvironment = { detectEnvironment: function () { const hostname = window.location.hostname; const pathname = window.location.pathname; // local or authoring experience where .html is needed if (hostname.includes('localhost') || hostname.includes('author') || pathname.includes('/editor.html') || pathname.includes('.html')) { return 'author'; } // check for dev/staging environments if (hostname.includes('wwwdev') || hostname.includes('wwwqa') || hostname.includes('wwwppe')) { return 'dev'; } // prod env if (hostname.includes('microsoft.com') && !hostname.includes('wwwdev')) { return 'production'; } return 'author'; }, // get current environment current: function () { if (!this._currentEnv) { this._currentEnv = this.detectEnvironment(); } return this._currentEnv; }, // Check if we should use .html extension useHtmlExtension: function () { return this.current() === 'author'; }, getPageExtension: function () { return this.useHtmlExtension() ? '.html' : ''; }, getPageNames: function () { const useHtml = this.useHtmlExtension(); return { HOMEPAGE: useHtml ? "blog.html" : "blog", CATEGORYPAGE: useHtml ? "category.html" : "category", TAGPAGE: useHtml ? "tag.html" : "tag", SEARCHPAGE: useHtml ? "search.html" : "search" }; }, getUrls: function () { const useHtml = this.useHtmlExtension(); const blogRoot = window.MsrcBlogUtils?.getBlogRootPath() || '/blog/'; return { tag: blogRoot + (useHtml ? "tag.html?tag=" : "tag?tag="), category: blogRoot + (useHtml ? "category.html?cat=" : "category?cat="), search: blogRoot + (useHtml ? "search.html?query=" : "search?query="), tagsPage: blogRoot + (useHtml ? "tags.html" : "tags"), categoriesPage: blogRoot + (useHtml ? "categories.html" : "categories") }; } }; }); (function (window) { if (!window.MsrcBlogUtils) { window.MsrcBlogUtils = {}; /** * Returns the blog root path, e.g. '/content/microsoft/msrc/en-us/blog/' */ window.MsrcBlogUtils.getBlogRootPath = function () { const match = window.location.pathname.match(/^(.*\/blog)(?:\.html)?\//i) || window.location.pathname.match(/^(.*\/blog)(?:\.html)?$/i); return match ? match[1] + "/" : "/blog/"; }; /** * Helper function to add sr20 parameter for wwwdev environment * @param {string} url - the base URL * @param {boolean} hasQueryParams - whether URL already has query parameters * @returns {string} URL with sr20 parameter if needed */ window.MsrcBlogUtils.addSr20Parameter = function (url, hasQueryParams = false) { const isWwwDev = window.location.hostname.includes('wwwdev'); if (isWwwDev) { const separator = hasQueryParams ? '&' : '?'; return url + separator + 'sr20=foxtrot'; } return url; }; /** * Centralized URL builder for blog pages - handles all environment logic * @param {string} type - 'search', 'tag', 'category', 'tags-page', 'categories-page' * @param {string} query - optional query parameter value * @returns {string} Complete URL ready to use */ window.MsrcBlogUtils.buildBlogUrl = function (type, query = '') { const useHtml = window.MsrcEnvironment?.useHtmlExtension() ?? (window.location.pathname.includes('.html') || window.location.hostname.includes('localhost')); const blogRoot = this.getBlogRootPath(); const origin = window.location.origin; let path, url; switch (type) { case 'search': path = blogRoot + (useHtml ? 'search.html' : 'search'); url = query ? `${origin}${path}?query=${encodeURIComponent(query)}` : `${origin}${path}?query=`; return this.addSr20Parameter(url, true); case 'tag': path = blogRoot + (useHtml ? 'tag.html' : 'tag'); url = query ? `${origin}${path}?tag=${encodeURIComponent(query)}` : `${origin}${path}?tag=`; return this.addSr20Parameter(url, true); case 'category': path = blogRoot + (useHtml ? 'category.html' : 'category'); url = query ? `${origin}${path}?cat=${encodeURIComponent(query)}` : `${origin}${path}?cat=`; return this.addSr20Parameter(url, true); case 'tags-page': path = blogRoot + (useHtml ? 'tags.html' : 'tags'); url = `${origin}${path}`; return this.addSr20Parameter(url, false); case 'categories-page': path = blogRoot + (useHtml ? 'categories.html' : 'categories'); url = `${origin}${path}`; return this.addSr20Parameter(url, false); default: url = `${origin}${blogRoot}`; return this.addSr20Parameter(url, false); } }; /** * Environment page link generation */ window.MsrcBlogUtils.getPageLink = function (permalink, basePath) { let newpath = permalink; if (permalink.endsWith("/")) { newpath = permalink.substring(0, permalink.length - 1); } let cleanBasePath = basePath; if (cleanBasePath.endsWith("/") && newpath.startsWith("/")) { cleanBasePath = cleanBasePath.slice(0, -1); } else if (!cleanBasePath.endsWith("/") && !newpath.startsWith("/")) { cleanBasePath = cleanBasePath + "/"; } const extension = window.MsrcEnvironment?.getPageExtension() || (window.location.pathname.includes('.html') ? '.html' : ''); let url = `${cleanBasePath + newpath + extension}`; return this.addSr20Parameter(url, false); }; window.MsrcBlogUtils.getHtmlDecode = function (input) { try { const doc = new DOMParser().parseFromString(input, "text/html"); return doc.documentElement.textContent; } catch (error) { console.warn('HTML decode failed, returning original input:', error); return input; } }; } })(window);