Skip to content

Instantly share code, notes, and snippets.

@lionelhorn
Forked from douglascayers/github-export-labels.js
Last active July 23, 2020 00:08
Show Gist options
  • Save lionelhorn/452278868d3ce8e6adb0c3375d8c19a3 to your computer and use it in GitHub Desktop.
Save lionelhorn/452278868d3ce8e6adb0c3375d8c19a3 to your computer and use it in GitHub Desktop.
Export and import GitHub labels between projects by running JavaScript in the browser console to automate clicks.
/**
* Inspired by @MoOx original script: https://gist.github.com/MoOx/93c2853fee760f42d97f
* Adds file download per @micalevisk https://gist.github.com/MoOx/93c2853fee760f42d97f#gistcomment-2660220
* Tweaked from @douglascayers https://gist.github.com/douglascayers/d47e525dbd1e7149bafa65939f350baf
*
* Changes include:
* - Get the description from the `title` attribute instead of `aria-label` (doesn't exist anymore)
* - Use style.backgroundColor and parse the rgb(...) to hex (rather than regex parsing of 'style' string)
* - Downloads labels to a JSON file named after the webpage to know which GitHub repo they came from.
*
* Last tested 2020-April-05:
* - 80.0.3987.149
*/
function exportGitHubLabels() {
let labels = [];
[].slice.call( document.querySelectorAll( '.js-label-link' ) )
.forEach( element => {
labels.push({
name: element.textContent.trim(),
description: element.getAttribute( 'title' ),
color: (
// style.backgroundColor returns "rgb(...)"
// but GitHub expects hex when we import the colors
element.style.backgroundColor
// grab between 'rgb(' and ')'
.substring( 4, element.style.backgroundColor.length - 1 )
// convert comma-delimited string into array of three numbers
.split( ',' )
// reduce array of three numbers into single hex color
.reduce( ( hexValue, rgbValue ) => {
return (
// append next two-digit hex value
hexValue +
// convert decimal to hex
Number( rgbValue ).toString( 16 )
// each number in a hex color is two characters
.padStart( 2, '0' )
);
}, '' )
)
});
});
return labels;
}
function saveDataAsJSON( data, filename ) {
const blob = new Blob( [ JSON.stringify( data, null, 4 ) ], { type: 'text/json' } );
const a = document.createElement( 'a' );
a.download = filename;
a.href = window.URL.createObjectURL( blob );
a.dataset.downloadurl = [ 'text/json', a.download, a.href ].join( ':' );
a.click();
}
saveDataAsJSON( exportGitHubLabels(), document.title + '.json' );
/**
* Inspired by @Isaddo original script: https://gist.github.com/Isaddo/7efebcb673a0957b9c6f07cd14826ea4
* Adds descriptions per @NillerMedDild https://gist.github.com/Isaddo/7efebcb673a0957b9c6f07cd14826ea4#gistcomment-2715349
*
* Changes include:
* - CSS selectors use `js` prefix
*
* Last tested 2019-July-27:
* - Chrome 75.0.3770.142
* - Safari 12.1.2
* - macOS 10.14.6
*/
function createLabel( label ) {
document.querySelector( '.js-new-label-name-input' ).value = label.name;
document.querySelector( '.js-new-label-description-input' ).value = label.description;
document.querySelector( '.js-new-label-color-input' ).value = '#' + label.color;
document.querySelector( '.js-details-target ~ .btn-primary' ).disabled = false;
document.querySelector( '.js-details-target ~ .btn-primary' ).click();
}
function updateLabel( label ) {
let updatedLabel = false;
[].slice.call( document.querySelectorAll( '.js-labels-list-item' ) ).forEach( element => {
if ( element.querySelector( '.js-label-link' ).textContent.trim() === label.name ) {
updatedLabel = true;
element.querySelector( '.js-edit-label' ).click();
element.querySelector( '.js-new-label-name-input' ).value = label.name;
element.querySelector( '.js-new-label-description-input' ).value = label.description;
element.querySelector( '.js-new-label-color-input' ).value = '#' + label.color;
element.querySelector( '.js-edit-label-cancel ~ .btn-primary' ).click();
}
});
return updatedLabel;
}
function createOrUpdate( label ) {
if ( !updateLabel( label ) ) {
createLabel( label );
}
}
[
// YOUR LABELS JSON HERE
].forEach( label => createOrUpdate( label ) );
[
{
"name": "P0",
"description": "High priority",
"color": "ef8783"
},
{
"name": "P1",
"description": "Medium priority",
"color": "f7d488"
},
{
"name": "P2",
"description": "Low priority",
"color": "4bcc74"
},
{
"name": "bug: crash 💥",
"description": "App crashes and is unusable in a significant way.",
"color": "fbca04"
},
{
"name": "bug: regression ↩️",
"description": "A new version of the app broke something.",
"color": "fbca04"
},
{
"name": "bug 🐞",
"description": "App is not working correctly.",
"color": "fbca04"
},
{
"name": "discussion 💬",
"description": "Discussing usage, best practices, questions, etc.",
"color": "e99695"
},
{
"name": "documentation 📓",
"description": "Related to improving documentation and the wiki.",
"color": "6addf7"
},
{
"name": "enhancement ✨",
"description": "A new feature suggestion or improvement upon an existing feature.",
"color": "84b6eb"
},
{
"name": "security 🔒",
"description": "Questions, concerns, or suggestions for improving the security of the app.",
"color": "1d76db"
},
{
"name": "status: in progress ❇️",
"description": "Currently being developed for a future release.",
"color": "c2e0c6"
},
{
"name": "status: on hold 💤",
"description": "Work has stopped. There may be one or more blockers or needs more information.",
"color": "c2e0c6"
},
{
"name": "status: resolved ✅",
"description": "This has been addressed in a branch and will be scheduled for release in the assigned milestone.",
"color": "c2e0c6"
}
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment