SharePoint Modern Site copy/save Theme to another site
In case you Provisioned a beautiful site with the PNP services of SharePoint LookBook, and you liked it, but wanted to take it out to another site...
Well, MS did not yet gave us a way to save/copy a Theme... just a lot of ways to upload ones...
I tried so mush downloading a site template with
Get-PnPProvisioningTemplate
Get-PnPSiteTemplate
Invoke-PnPSiteTemplate
All failed for so many reasons... BTW (1) dont change the name of the .pnp file, and if you get some "access denied" error, either become global admin, or use "-ExcludeHandlers" (i needed Fields, Files, Lists, Pages)
Anyways... how I got it working
1. I used this endpoint to get the actual palette
https://tenant.sharepoint.com/sites/NewEmployeeOnboardingNew/_api/SP.Web.GetContextWebThemeData
2. And extraced the data accroding to this MS article while converting the RGB to HEX
code made in html/js in the end
3. I uploaded the theme to the Tenant
With SPO services, for some reason, you can't connect anymore to a single site, only to the entire Tenant, more specifically to the admin, i.e. https://tenant-admin.sharepoint.com and therefor the theme will now be available through all sites (settings -> change the look -> theme)
The PS commands:
Connect-SPOService -Url https://tenant-admin.sharepoint.com
Add-SPOTheme -Identity "like grey" -Palette $themepalette -IsInverted $false
Enjoy!
Instructions for converter
0. create html file with the code below and double click it
1. Go to via browser
https://tenant.sharepoint.com/sites/NewEmployeeOnboardingNew/_api/SP.Web.GetContextWebThemeData
2. Copy everything
3. Paste in the text box
4. click button
5. paste in PS
6. run the PS commands above
CODE for Converter
<body>
<style>body { width: 70%; margin: auto;margin-top: 71px;}textarea { width: 100%; height: 300px; }</style>
<h1>your /_api/SP.Web.GetContextWebThemeData to $themepalette</h1>
<div><textarea id="in"></textarea></div>
<div><button onclick="clicks()" >clicks</button></div>
<div id="res"></div>
<script>
function clicks(){
console.log('here')
let d = document.querySelector("#in").value
d = d.replace('<d:GetContextWebThemeData xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:georss="http://www.georss.org/georss" xmlns:gml="http://www.opengis.net/gml">', '')
d = d.replace('</d:GetContextWebThemeData>', '')
d = d.replace('This XML file does not appear to have any style information associated with it. The document tree is shown below.', '')
d = d.trim()
let j = JSON.parse(d)
j = j.Palette.Colors
console.log(j)
let out = '$themepalette = @{ '
let keys = ["themePrimary", "themeLighterAlt", "themeLighter", "themeLight"
, "themeTertiary", "themeSecondary", "themeDarkAlt", "themeDark"
, "themeDarker", "neutralLighterAlt", "neutralLighter", "neutralLight"
, "neutralQuaternaryAlt", "neutralQuaternary", "neutralTertiaryAlt", "neutralTertiary"
, "neutralSecondaryAlt", "neutralSecondary", "neutralPrimary", "neutralPrimaryAlt"
, "neutralDark", "black", "white", "primaryBackground", "primaryText"]
for (let i = 0; i < keys.length; i++) {
const k = keys[i];
if (!j[k]) {
console.log(`no key ${k}`)
continue
}
out += `"${k}" = "${dcRgbToHex(j[k])}"; `
}
out += '}'
console.log(out)
let ta = document.querySelector("#in")
ta.value = out
ta.select();
document.execCommand("copy");
}
function dcRgbToHex(dc){
dc = dc.DefaultColor
return rgbToHex(dc.R, dc.G, dc.B)
}
function componentToHex(c) {
var hex = c.toString(16);
return hex.length == 1 ? "0" + hex : hex;
}
function rgbToHex(r, g, b) {
return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
}
</script>
</body>
Comments
Post a Comment