#import "custom_html.typ" as chtml // Need inline svg for css color control, so no `image` element :( #let clipboard-icon = html.elem( "svg", attrs: ( //width: "16", //height: "16", style: "width: 1.5em; height: 1.5em;", fill: "currentcolor", viewBox: "0 0 16 16", xmlns: "http://www.w3.org/2000/svg" ), { html.elem("path", attrs: ( d: "M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z" )) html.elem("path", attrs: ( d: "M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z" )) } ) #let code-block-counter = state("code-block-counter", 0) #let show-rule-code-block(code) = context { let code-id = code-block-counter.get() let code-id-name = "code-block-" + str(code-id) ```raw-css code-block { display: flex; justify-content: space-between; overflow: hidden; border-radius: 8px; margin: 8px; background-color: var(--color-code-bg); box-shadow: inset 0px 0px 5px 0px #000; pre { padding: 8px; margin: 0; overflow: auto; } code-block-button-container { display: block; button { background-color: inherit; border: inherit; border-radius: 4px; padding: 8px; margin: 4px; &:hover { box-shadow: inset 0px 0px 0.4em 0px var(--color-button-shadow); cursor: pointer; } } @media (not (scripting: enabled)) { .code-block-clipboard-button { display: none; } } } } ``` ```raw-js function copy_code_to_clipboard(id) { code = document.getElementById(id).getAttribute("code-value"); navigator.clipboard.writeText(code).then( (r) => alert("copy: " + code), (e) => alert("failed to copy code: ", e), ) } ``` chtml.code-block( attrs: ( id: code-id-name, code-value: code.text, ), { code chtml.code-block-button-container({ html.elem( "button", attrs: ( class: "code-block-clipboard-button", onclick: "copy_code_to_clipboard('" + code-id-name + "');", aria-label: "copy to clipboard button", ), { clipboard-icon } ) }) } ) code-block-counter.update(x => x+1) }