diff --git a/lib/code.typ b/lib/code.typ new file mode 100644 index 0000000..ab68427 --- /dev/null +++ b/lib/code.typ @@ -0,0 +1,102 @@ +#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) +} diff --git a/lib/custom_html.typ b/lib/custom_html.typ index 64d666b..8d3e1e7 100644 --- a/lib/custom_html.typ +++ b/lib/custom_html.typ @@ -12,6 +12,8 @@ html.elem("theme-picker", attrs: (aria-label: label, role: "radiogroup"), body) } #let code-block = html.elem.with("code-block") +#let code-block-button-container = html.elem.with("code-block-button-container") + #let icon-container(..args, body) = { html.elem("icon-container", attrs: args.named(), body) } diff --git a/lib/html_body.typ b/lib/html_body.typ index da3ce31..6834635 100644 --- a/lib/html_body.typ +++ b/lib/html_body.typ @@ -65,7 +65,7 @@ site-container { display: flex; flex-direction: column; - max-width: 1510px; + max-width: 60em; width: 100%; padding: 0 20px; @@ -90,20 +90,6 @@ margin-top: 15px; } } - - code-block { - display: flex; - justify-content: center; - align-items: center; - - pre { - width: min-content; - padding: 8px; - border-radius: 8px; - background-color: var(--color-code-bg); - box-shadow: inset 0px 0px 5px 0px #000; - } - } } ``` set figure(supplement: none) diff --git a/lib/html_head.typ b/lib/html_head.typ index 1535bd2..324221f 100644 --- a/lib/html_head.typ +++ b/lib/html_head.typ @@ -1,5 +1,5 @@ #import "./custom_html.typ" as chtml -#import "./html_utils.typ": get-css +#import "./html_utils.typ": get-css, get-js /// Generate the html
element for the page. #let html_head( @@ -87,6 +87,7 @@ }} html.style(get-css()) + html.script(get-js()) }) } diff --git a/lib/html_utils.typ b/lib/html_utils.typ index e06e478..06810c9 100644 --- a/lib/html_utils.typ +++ b/lib/html_utils.typ @@ -1,26 +1,40 @@ -#import "./custom_html.typ": code-block #import "./figures.typ": show-rule-figure +#import "./code.typ": show-rule-code-block #let css-list = state("css-list", ()) +#let js-list = state("js-list", ()) /// Add string `css` to `css-list` if not already present #let add-css(css) = context { css-list.update(x => if css in x { x } else { x + (css,) }) } +/// Add string `js` to `js-list` if not already present +#let add-js(js) = context { + js-list.update(x => if js in x { x } else { x + (js,) }) +} + /// Concatenate all css found in css-list at the end of the document #let get-css() = context { css-list.final().join("\n\n") } +/// Concatenate all js found in js-list at the end of the document +#let get-js() = context { + js-list.final().join("\n\n") +} + #let html_show(body) = { show raw: it => { if it.lang == "raw-css" { // remove code and add it to css style add-css(it.text) + } else if it.lang == "raw-js" { + // remove code and add it to css style + add-js(it.text) } else if it.block { // wrap inside a
- code-block(it)
+ show-rule-code-block(it)
} else {
it
}
diff --git a/lib/summary.typ b/lib/summary.typ
index 0685db9..7596b9b 100644
--- a/lib/summary.typ
+++ b/lib/summary.typ
@@ -36,7 +36,7 @@
summary-card-description {
display: flex;
flex-direction: column;
- text-align: left;
+ text-align: justify;
height: 100%;
h3 {
@@ -45,8 +45,9 @@
}
summary-card-details {
+ text-align: left;
margin-top: auto;
- padding-top: 0.5em;
+ padding-top: 1em;
}
}
diff --git a/test_template/main.typ b/test_template/main.typ
index 51de1f8..cca7e15 100644
--- a/test_template/main.typ
+++ b/test_template/main.typ
@@ -75,6 +75,8 @@ def plopliplop(n: int)
print(i)
```
+#raw(range(10).map(i => lorem(100)).join("\n"), block: true)
+
/*
#figure({
show table: set text(size: 0.80em)
@@ -163,6 +165,7 @@ thead {
)
#card-list(
+ min-width: 200,
range(1, 21).map(i =>
summary(
url: "http://test.example.com",