Skip to content

Instantly share code, notes, and snippets.

@WojtekCodesToday
Created April 7, 2023 17:26
Show Gist options
  • Save WojtekCodesToday/7d7aa6fb21c0acae76cb0e0021cfac1e to your computer and use it in GitHub Desktop.
Save WojtekCodesToday/7d7aa6fb21c0acae76cb0e0021cfac1e to your computer and use it in GitHub Desktop.
Roost is a library to use JSX and render it, it's very good and MAYBE better than React.
const roost = {
elements: {},
render: function (json, parent = document.body) {
if (typeof json === 'string') {
const element = document.createElement('div');
element.innerHTML = json.trim();
if (parent) {
parent.appendChild(element.firstChild);
}
return element.firstChild;
}
const element = document.createElement(json.type);
if (json.props) {
Object.keys(json.props).forEach(name => {
if (name.startsWith('on')) {
const eventType = name.substring(2).toLowerCase();
element.addEventListener(eventType, json.props[name]);
} else {
element.setAttribute(name, json.props[name]);
}
});
}
if (parent) {
parent.appendChild(element);
}
if (json.children) {
json.children.forEach(child => this.render(child, element));
}
return element;
},
jsx: function (jsx) {
const pattern = /<(\w+)\s*\/?>/g;
const elements = [];
let match;
let last = 0;
while ((match = pattern.exec(jsx))) {
if (match.index > last) {
const text = jsx.substring(last, match.index);
elements.push({ type: "text", value: text });
}
const tagName = match[1];
const selfClosing = match[0].endsWith("/");
const props = {};
const propPattern = /(\w+)="([^"]*)"/g;
let propMatch;
while ((propMatch = propPattern.exec(match[0]))) {
const propName = propMatch[1];
const propValue = propMatch[2];
props[propName] = propValue;
}
elements.push({ type: "element", tagName, selfClosing, props });
last = pattern.lastIndex;
}
if (last < jsx.length) {
const text = jsx.substring(last);
elements.push({ type: "text", value: text });
}
return elements;
},
convertToDOM: function (json) {
const elements = [];
for (const item of json) {
if (item.type === "text") {
elements.push(document.createTextNode(item.value));
} else if (item.type === "element") {
const element = document.createElement(item.tagName);
for (const [key, value] of Object.entries(item.props)) {
if (key === "className") {
element.setAttribute("class", value);
} else if (key === "id") {
element.setAttribute("id", value);
} else {
element.setAttribute(key, value);
}
}
if (!item.selfClosing) {
const children = this.convertToDOM(item.children);
for (const child of children) {
element.appendChild(child);
}
}
elements.push(element);
}
}
return elements;
},
};
export default roost;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment