201 lines
6.5 KiB
TypeScript
201 lines
6.5 KiB
TypeScript
import { ITrainingTip, WalkthroughConfigs } from "./TrainingInterfaces";
|
|
|
|
const colorOptions = [
|
|
'red', 'blue', 'green', 'purple', 'pink', 'indigo', 'teal', 'orange', 'cyan', 'emerald', 'sky', 'violet', 'fuchsia', 'rose', 'lime', 'slate'
|
|
]
|
|
|
|
const getRandomColors = (count: number) => {
|
|
const shuffled = [...colorOptions].sort(() => 0.5 - Math.random());
|
|
return shuffled.slice(0, count);
|
|
};
|
|
|
|
const classMap = {
|
|
"mainDiv": {
|
|
"tip": "flex-col gap-2",
|
|
"question": "flex-col gap-2",
|
|
"additional": "flex-col gap-8",
|
|
"segment": "p-4 rounded-lg mb-4 flex flex-col gap-2"
|
|
},
|
|
"h2": {
|
|
"tip": "mb-4 font-semibold text-lg",
|
|
"question": "text-lg font-semibold mb-4",
|
|
"additional": "text-2xl font-semibold mb-4",
|
|
"segment": "text-xl font-semibold"
|
|
}
|
|
}
|
|
|
|
const setClass = (element: Element, style: string) => {
|
|
element.setAttribute('class', style)
|
|
}
|
|
|
|
|
|
// DON'T OVERRIDE DIV AND SPAN STYLES
|
|
const processHtml = (section: string, html: string, color: string) => {
|
|
const parser = new DOMParser();
|
|
const doc = parser.parseFromString(html, 'text/html');
|
|
|
|
const mainDiv = doc.body.firstElementChild;
|
|
if (mainDiv && mainDiv.tagName === 'DIV') {
|
|
if (section === "segment") {
|
|
setClass(mainDiv, `bg-${color}-100 ${classMap["mainDiv"][section]}`);
|
|
} else {
|
|
setClass(mainDiv, classMap["mainDiv"][section as keyof typeof classMap["mainDiv"]]);
|
|
}
|
|
}
|
|
|
|
doc.querySelectorAll('h1').forEach(e => {
|
|
if (section === "additional") {
|
|
setClass(e, 'text-4xl font-bold mb-6')
|
|
} else {
|
|
setClass(e, 'text-xl font-semibold mb-4');
|
|
}
|
|
});
|
|
|
|
doc.querySelectorAll('h2').forEach(e => {
|
|
setClass(e, classMap["h2"][section as keyof typeof classMap["h2"]])
|
|
});
|
|
|
|
doc.querySelectorAll('h3').forEach(e => {
|
|
e.setAttribute('class', 'text-lg font-semibold mb-4')
|
|
})
|
|
|
|
doc.querySelectorAll('p').forEach(e => {
|
|
if (section === "segment") {
|
|
setClass(e, 'text-gray-700 leading-relaxed')
|
|
} else {
|
|
setClass(e, 'mb-4');
|
|
}
|
|
});
|
|
|
|
doc.querySelectorAll('label').forEach(e => {
|
|
if (section === "additional") {
|
|
setClass(e, 'font-semibold');
|
|
} else {
|
|
setClass(e, 'min-w-[16px] mr-1 font-semibold');
|
|
}
|
|
});
|
|
|
|
doc.querySelectorAll('ul').forEach(e => {
|
|
const hasLabel = Array.from(e.querySelectorAll('li')).some(li => li.querySelector('label'));
|
|
if (hasLabel) {
|
|
e.setAttribute('class', 'list-none space-y-2');
|
|
} else {
|
|
e.setAttribute('class', `list-disc pl-5 space-y-2`);
|
|
}
|
|
});
|
|
|
|
doc.querySelectorAll('ol').forEach(e => {
|
|
e.setAttribute('class', 'list-decimal pl-5 space-y-2');
|
|
})
|
|
|
|
doc.querySelectorAll('hz-row').forEach(e => {
|
|
e.setAttribute('class', `flex flex-row items-center mb-4 gap-2`);
|
|
})
|
|
|
|
if (section === "segment") {
|
|
doc.querySelectorAll('b').forEach(e => {
|
|
e.setAttribute('class', `text-${color}-700`);
|
|
});
|
|
}
|
|
|
|
doc.querySelectorAll('section').forEach(e => {
|
|
e.setAttribute('class', `mb-8`);
|
|
});
|
|
|
|
doc.querySelectorAll('option-box').forEach(e => {
|
|
e.setAttribute('class', `flex justify-center min-w-[32px] min-h-6 bg-gray-200 rounded`);
|
|
});
|
|
|
|
doc.querySelectorAll('option-box-grow').forEach(e => {
|
|
e.setAttribute('class', 'flex flex-grow ml-2 w-10 min-h-6 bg-gray-200 rounded px-4 py-2');
|
|
})
|
|
|
|
doc.querySelectorAll('option-box-blank').forEach(e => {
|
|
e.setAttribute('class', 'min-w-[32px] min-h-[32px] border border-gray-300 text-center mr-3 flex justify-center items-center');
|
|
})
|
|
|
|
doc.querySelectorAll('option-card').forEach(e => {
|
|
e.setAttribute('class', 'bg-gray-100 rounded-lg flex flex-col p-4')
|
|
})
|
|
|
|
doc.querySelectorAll('footer').forEach(e => {
|
|
e.setAttribute('class', `flex flex-col gap-2 text-sm`);
|
|
});
|
|
|
|
doc.querySelectorAll('single-line').forEach(e => {
|
|
e.setAttribute('class', `border-b border-black w-full h-4 inline-block`);
|
|
})
|
|
|
|
doc.querySelectorAll('padded-line').forEach(e => {
|
|
e.setAttribute('class', `my-2 inline-block w-full`);
|
|
})
|
|
|
|
doc.querySelectorAll('table').forEach(table => {
|
|
table.setAttribute('class', 'min-w-full bg-white border border-gray-300')
|
|
|
|
table.querySelectorAll('thead tr').forEach(tr => {
|
|
tr.setAttribute('class', 'bg-gray-100');
|
|
});
|
|
|
|
table.querySelectorAll('th').forEach(th => {
|
|
th.setAttribute('class', 'py-2 px-4 border-b font-semibold text-left');
|
|
});
|
|
|
|
table.querySelectorAll('tbody tr').forEach((tr, index) => {
|
|
if (index % 2 === 1) {
|
|
tr.setAttribute('class', 'bg-gray-50');
|
|
}
|
|
});
|
|
|
|
table.querySelectorAll('td').forEach(td => {
|
|
if (td === td.parentElement?.firstElementChild) {
|
|
td.setAttribute('class', 'py-2 px-4 border-b font-medium');
|
|
} else {
|
|
td.setAttribute('class', 'py-2 px-4 border-b');
|
|
}
|
|
});
|
|
});
|
|
|
|
doc.querySelectorAll('blockquote').forEach(e => {
|
|
setClass(e, `flex w-full justify-center ${section === "segment" ? "" : "mb-4"}`)
|
|
})
|
|
|
|
doc.querySelectorAll('items-between').forEach(e => {
|
|
setClass(e, 'flex flex-row justify-between mb-4')
|
|
})
|
|
|
|
return doc.body.innerHTML;
|
|
}
|
|
|
|
const formatTip = (tip: ITrainingTip): ITrainingTip => {
|
|
if (tip.exercise && tip.exercise.segments) {
|
|
const colors = getRandomColors(tip.exercise.segments.length);
|
|
|
|
const processedSegments: WalkthroughConfigs[] = tip.exercise.segments.map((segment, index) => ({
|
|
...segment,
|
|
html: processHtml("segment", segment.html, colors[index])
|
|
}));
|
|
|
|
return {
|
|
id: tip.id,
|
|
tipCategory: tip.tipCategory,
|
|
tipHtml: processHtml("tip", tip.tipHtml, ""),
|
|
standalone: tip.standalone,
|
|
exercise: {
|
|
question: processHtml("question", tip.exercise.question, ""),
|
|
additional: tip.exercise.additional ? processHtml("additional", tip.exercise.additional, "") : undefined,
|
|
segments: processedSegments
|
|
}
|
|
};
|
|
}
|
|
|
|
return {
|
|
id: tip.id,
|
|
tipCategory: tip.tipCategory,
|
|
tipHtml: processHtml("tip", tip.tipHtml, ""),
|
|
standalone: tip.standalone,
|
|
exercise: undefined
|
|
};
|
|
};
|
|
|
|
export default formatTip; |