Skip to content

Instantly share code, notes, and snippets.

@Phoenix616
Last active January 23, 2025 21:50
Show Gist options
  • Save Phoenix616/ae58fd59f68f33e783ead14f1f7ac4ec to your computer and use it in GitHub Desktop.
Save Phoenix616/ae58fd59f68f33e783ead14f1f7ac4ec to your computer and use it in GitHub Desktop.
Create HTML text from Minecraft text components. (does not support special stuff like translatables and entity/item data)
/**
* Copyright (c) 2025 Phoenix616 ([email protected])
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
function jsonComponentToHtml(json) {
const element = document.createElement('span');
if (json.clickEvent) {
element.onclick = function () {
if (json.clickEvent.action === 'run_command') {
// run command
} else if (json.clickEvent.action === 'open_url') {
window.open(json.clickEvent.value, '_blank');
} else if (json.clickEvent.action === 'suggest_command') {
// suggest to user in some way
} else if (json.clickEvent.action === 'change_page') {
// change page
} else if (json.clickEvent.action === 'copy_to_clipboard') {
navigator.clipboard.writeText(json.clickEvent.value);
}
};
element.style.cursor = 'pointer';
}
if (json.hoverEvent) {
element.onmouseover = function (event) {
if (json.hoverEvent.action === 'show_text') {
if (json.hoverEvent.content) {
showHover(jsonComponentToHtml(json.hoverEvent.content), event.x, window.innerHeight - event.y);
} else {
showHover(jsonComponentToHtml(json.hoverEvent.value), event.x, window.innerHeight - event.y);
}
}
};
element.onmouseout = function () {
removeHover();
};
}
if (json.text) {
element.innerText = json.text;
} else if (!json.extra) {
element.innerText = json.toString();
}
if (json.color) {
if (json.color.startsWith('#')) {
element.style.color = json.color;
} else {
element.style.color = getMinecraftColor(json.color);
}
}
if (json.italic === true) {
element.style.fontStyle = 'italic';
} else if (json.italic === false) {
element.style.fontStyle = 'normal';
}
if (json.bold === true) {
element.style.fontWeight = 'bold';
} else if (json.bold === false) {
element.style.fontWeight = 'normal';
}
if (json.underlined === true) {
element.style.textDecoration += 'underline';
}
if (json.strikethrough === true) {
element.style.textDecoration += 'line-through';
}
if (json.underlined === false && json.strikethrough === false) {
element.style.textDecoration = 'none';
}
if (json.obfuscated === true) {
element.style.filter = 'blur(1px)';
} else if (json.obfuscated === false) {
element.style.filter = 'none';
}
if (json.extra) {
json.extra.forEach(extra => {
element.append(jsonComponentToHtml(extra));
});
}
return element;
}
function showHover(component, x, y) {
const hover = document.createElement('div');
hover.id = 'text-hover';
hover.style.position = 'absolute';
hover.style.zIndex = '9001';
hover.style.backgroundColor = 'rgba(16,0,16,0.94)';
hover.style.color = 'white';
hover.style.border = '0.125em solid #2D0A63';
hover.style.borderRadius = '2px';
hover.style.padding = '0.375em';
hover.style.bottom = `${y + 12}px`;
hover.style.left = `${x + 12}px`;
hover.append(component);
document.body.append(hover);
}
function removeHover() {
const hover = document.getElementById('text-hover');
if (hover) {
hover.remove();
}
}
function getMinecraftColor(color) {
switch (color) {
case 'black':
return '#000000';
case 'dark_blue':
return '#0000AA';
case 'dark_green':
return '#00AA00';
case 'dark_aqua':
return '#00AAAA';
case 'dark_red':
return '#AA0000';
case 'dark_purple':
return '#AA00AA';
case 'gold':
return '#FFAA00';
case 'gray':
return '#AAAAAA';
case 'dark_gray':
return '#555555';
case 'blue':
return '#5555FF';
case 'green':
return '#55FF55';
case 'aqua':
return '#55FFFF';
case 'red':
return '#FF5555';
case 'light_purple':
return '#FF55FF';
case 'yellow':
return '#FFFF55';
case 'white':
return '#FFFFFF';
default:
return '#FFFFFF';
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment