#import "../utilities/localize.typ": localize #let skill(data, language) = { // Determine the color to use for the proficiency percentage bar. let proficiency_color = if "color" in data { // If there is a color defined in the data, use `eval()` to convert it to a // Typst color. eval(data.color) } else { // Otherwise if no color is defined default to black. black } let proficiency_percentage = str(data.proficiency) + "%"; // Use a stack to position the text and percentage bar from top to bottom. stack( dir: ttb, // And use a grid to position the skill text and percentage number from // left to right. grid( columns: (1fr, auto), localize(data, "name", language), proficiency_percentage, ), // Add a tiny amount of vertical space so the bar doesn't overlap the text. v(4pt), // Then render the bar as two lines where the grid columns determine how // long they both are. Initially I tried to do this with a linear gradient // and using the percentage as a color stop, but it left a small fade in // between the colors which I didn't want. grid( // We have to use `eval()` for the percentage here as it's still a string // at this point and Typst expects a ratio type to calculate with. columns: (1fr, 100% - eval(proficiency_percentage)), line(length: 100%, stroke: 1pt + proficiency_color), line(length: 100%, stroke: 1pt + silver), ), ) } #let skills_section(data, language) = { block(stroke: (left: 1pt + black), outset: (left: 0.75em), [ == #localize(data.locale, "skills", language) // Define all the sections to render, the order here also determines the // render order. #for skill_section in ("language", "general", "software", "platforms") [ === #localize(data, skill_section, language) #for data in data.skills.at(skill_section) { skill(data, language) } ] ]) }