Org html: add copy button to src/example block

This commit is contained in:
TEC 2020-07-18 02:43:52 +08:00
parent d6d608304c
commit 9ba5a35f96
7 changed files with 237 additions and 51 deletions

View File

@ -4638,7 +4638,7 @@ Suffice to say I've snatched it, with a few of my own tweaks applied.
(setq org-html-style-default
(concat (f-read-text (expand-file-name "misc/org-export-header.html" doom-private-dir))
"<script>\n"
(f-read-text (expand-file-name "misc/pile-css-theme/toc.js" doom-private-dir))
(f-read-text (expand-file-name "misc/pile-css-theme/main.js" doom-private-dir))
"</script>\n<style>\n"
(f-read-text (expand-file-name "misc/pile-css-theme/main.css" doom-private-dir))
"</style>")
@ -4659,11 +4659,17 @@ somewhat spiffy.
(lang (mode-name-to-lang-name
(plist-get properties :language)))
(name (plist-get properties :name)))
(format "<details class='code' open><summary%s>%s</summary>%s</details>"
(if name " class='named'" "")
(if (not name) (concat "<span class='lang'>" lang "</span>")
(format "<span class='name'>%s</span><span class='lang'>%s</span>" name lang))
(funcall orig-fn src-block contents info))))
(format
"<details class='code' open><summary%s>%s</summary>
<div class='gutter'>
<button title='Copy to clipboard' onclick='copyPreToClipdord(this)'>⎘</button>\
</div>
%s
</details>"
(if name " class='named'" "")
(if (not name) (concat "<span class='lang'>" lang "</span>")
(format "<span class='name'>%s</span><span class='lang'>%s</span>" name lang))
(funcall orig-fn src-block contents info))))
(defun mode-name-to-lang-name (mode)
(or (cadr (assoc mode
@ -4747,8 +4753,7 @@ somewhat spiffy.
("vhdl" "VHDL")
("xml" "XML")
("nxml" "XML")
("conf" "Configuration File")
)))
("conf" "Configuration File"))))
mode))
#+END_SRC
@ -4757,9 +4762,13 @@ somewhat spiffy.
(after! org
(defun org-html-block-collapsable (orig-fn block contents info)
"Wrap the usual block in a <details>"
(concat "<details class='code' open><summary></summary>"
(funcall orig-fn block contents info)
"</details>"))
(concat
"<details class='code' open><summary></summary>
<div class='gutter'>\
<button title='Copy to clipboard' onclick='copyPreToClipdord(this)'>⎘</button>\
</div>\n"
(funcall orig-fn block contents info)
"</details>"))
(advice-add 'org-html-example-block :around #'org-html-block-collapsable)
(advice-add 'org-html-fixed-width :around #'org-html-block-collapsable)

View File

@ -3,8 +3,15 @@
Sass files for my org exporting. Taken from [[github:lepisma/pile-theme][lepisma/pile-theme]].
#+NAME: om-sass
#+BEGIN_SRC shell :exports none
#+BEGIN_SRC shell :exports none :results output
sassc main.scss main.css
#+END_SRC
#+RESULTS: om-sass
#+NAME: make-js
#+BEGIN_SRC shell :exports none :results output
cat _*.js > main.js
#+END_SRC
#+RESULTS: make-js

View File

@ -0,0 +1,8 @@
function copyPreToClipdord(btn) {
const pre = btn.parentElement.parentElement.getElementsByTagName("PRE")[0];
const range = document.createRange();
range.selectNode(pre);
window.getSelection().addRange(range);
var successful = document.execCommand('copy');
window.getSelection().removeRange(range);
}

View File

@ -68,6 +68,7 @@ li {
// folding
details.code {
position: relative;
summary {
position: relative;
left: -3px;
@ -100,7 +101,7 @@ details.code {
margin-bottom: -26px;
}
&:not([open]) summary {
margin-bottom: -10px;
margin-bottom: -5px;
}
}
@ -108,6 +109,9 @@ details.code {
p + details.code {
margin-top: -20px; // pre margin size
}
li p + details.code {
margin-top: -5px;
}
// Palette copied from blog
// ------------------------
@ -168,6 +172,30 @@ $code-warning: $orange;
}
}
// copy button
details.code > .gutter {
position: absolute;
top: 0;
left: -2.5rem;
width: 2.3rem;
padding-top: 10px;
height: calc(100% - 10px);
z-index: 1;
text-align: right;
transition: opacity 200ms;
opacity: 0;
font-size: 15px;
&:hover {
opacity: 1;
}
button {
color: $text-gray;
background: none;
border: none;
}
}
/* Languages per Org manual */
pre.src-asymptote::before { content: 'Asymptote'; }

View File

@ -441,8 +441,8 @@ template {
#switch-label {
left: auto;
left: bottom;
right: 1%;
top: 2.5rem; } }
right: 1vw;
top: 1vh; } }
#switch-label::before {
content: var(--switch-icon);
@ -1141,45 +1141,46 @@ li code {
li p code {
font-size: 15px; }
details.code summary {
position: relative;
left: -3px;
padding-left: 10px;
padding-botton: 4px;
margin-left: -10px;
z-index: 1;
outline: none;
font-family: "Open Sans";
font-weight: normal;
font-style: normal;
font-size: 12px;
line-height: 1.9;
color: var(--text-light); }
details.code summary .name {
font-size: 14px;
color: var(--text-medium);
margin-right: 0.7em; }
details.code summary .lang {
font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace;
font-style: italic; }
details.code summary::marker {
color: var(--back-medium); }
details.code[open] summary {
margin-bottom: -32px; }
details.code[open] summary .lang {
color: transparent; }
details.code[open] summary.named {
margin-bottom: -26px; }
details.code:not([open]) summary {
margin-bottom: -10px; }
details.code {
position: relative; }
details.code summary {
position: relative;
left: -3px;
padding-left: 10px;
padding-botton: 4px;
margin-left: -10px;
z-index: 1;
outline: none;
font-family: "Open Sans";
font-weight: normal;
font-style: normal;
font-size: 12px;
line-height: 1.9;
color: var(--text-light); }
details.code summary .name {
font-size: 14px;
color: var(--text-medium);
margin-right: 0.7em; }
details.code summary .lang {
font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace;
font-style: italic; }
details.code summary::marker {
color: var(--back-medium); }
details.code[open] summary {
margin-bottom: -32px; }
details.code[open] summary .lang {
color: transparent; }
details.code[open] summary.named {
margin-bottom: -26px; }
details.code:not([open]) summary {
margin-bottom: -5px; }
p + details.code {
margin-top: -20px; }
li p + details.code {
margin-top: -5px; }
.example,
.src {
color: var(--code-foreground); }
@ -1225,6 +1226,25 @@ p + details.code {
.src .org-highlight-numbers-number {
color: var(--code-const); }
details.code > .gutter {
position: absolute;
top: 0;
left: -2.5rem;
width: 2.3rem;
padding-top: 10px;
height: calc(100% - 10px);
z-index: 1;
text-align: right;
transition: opacity 200ms;
opacity: 0;
font-size: 15px; }
details.code > .gutter:hover {
opacity: 1; }
details.code > .gutter button {
color: var(--text-gray);
background: none;
border: none; }
/* Languages per Org manual */
pre.src-asymptote::before {
content: 'Asymptote'; }
@ -1789,7 +1809,82 @@ dl a {
#crosslinks a:not(.highlight)[href^="#"],
li a[href^="#"],
dl a[href^="#"] {
color: var(--text-gray); }
text-shadow: 0.03em 0 var(--back-white), -0.03em 0 var(--back-white), 0 0.03em var(--back-white), 0 -0.03em var(--back-white), 0.06em 0 var(--back-white), -0.06em 0 var(--back-white), 0.09em 0 var(--back-white), -0.09em 0 var(--back-white), 0.12em 0 var(--back-white), -0.12em 0 var(--back-white), 0.15em 0 var(--back-white), -0.15em 0 var(--back-white);
background-image: linear-gradient(var(--text-gray), var(--text-gray));
background-size: 1px 1px;
background-repeat: repeat-x;
background-position: 0% 95%;
border-radius: 1px;
color: var(--text-gray);
text-decoration: none; }
#breadcrumbs a[href^="#"]::selection,
figcaption a[href^="#"]::selection,
p a[href^="#"]::selection,
.page-tags a[href^="#"]::selection,
table a[href^="#"]::selection,
#crosslinks a:not(.highlight)[href^="#"]::selection,
li a[href^="#"]::selection,
dl a[href^="#"]::selection {
text-shadow: 0.03em 0 var(--back-medium), -0.03em 0 var(--back-medium), 0 0.03em var(--back-medium), 0 -0.03em var(--back-medium), 0.06em 0 var(--back-medium), -0.06em 0 var(--back-medium), 0.09em 0 var(--back-medium), -0.09em 0 var(--back-medium), 0.12em 0 var(--back-medium), -0.12em 0 var(--back-medium), 0.15em 0 var(--back-medium), -0.15em 0 var(--back-medium);
background: var(--back-medium); }
#breadcrumbs a[href^="#"]::-moz-selection,
figcaption a[href^="#"]::-moz-selection,
p a[href^="#"]::-moz-selection,
.page-tags a[href^="#"]::-moz-selection,
table a[href^="#"]::-moz-selection,
#crosslinks a:not(.highlight)[href^="#"]::-moz-selection,
li a[href^="#"]::-moz-selection,
dl a[href^="#"]::-moz-selection {
text-shadow: 0.03em 0 var(--back-medium), -0.03em 0 var(--back-medium), 0 0.03em var(--back-medium), 0 -0.03em var(--back-medium), 0.06em 0 var(--back-medium), -0.06em 0 var(--back-medium), 0.09em 0 var(--back-medium), -0.09em 0 var(--back-medium), 0.12em 0 var(--back-medium), -0.12em 0 var(--back-medium), 0.15em 0 var(--back-medium), -0.15em 0 var(--back-medium);
background: var(--back-medium); }
#breadcrumbs a[href^="#"] *,
#breadcrumbs a[href^="#"] *:after, #breadcrumbs a[href^="#"]:after,
#breadcrumbs a[href^="#"] *:before, #breadcrumbs a[href^="#"]:before,
figcaption a[href^="#"] *,
figcaption a[href^="#"] *:after,
figcaption a[href^="#"]:after,
figcaption a[href^="#"] *:before,
figcaption a[href^="#"]:before,
p a[href^="#"] *,
p a[href^="#"] *:after,
p a[href^="#"]:after,
p a[href^="#"] *:before,
p a[href^="#"]:before,
.page-tags a[href^="#"] *,
.page-tags a[href^="#"] *:after,
.page-tags a[href^="#"]:after,
.page-tags a[href^="#"] *:before,
.page-tags a[href^="#"]:before,
table a[href^="#"] *,
table a[href^="#"] *:after,
table a[href^="#"]:after,
table a[href^="#"] *:before,
table a[href^="#"]:before,
#crosslinks a:not(.highlight)[href^="#"] *,
#crosslinks a:not(.highlight)[href^="#"] *:after,
#crosslinks a:not(.highlight)[href^="#"]:after,
#crosslinks a:not(.highlight)[href^="#"] *:before,
#crosslinks a:not(.highlight)[href^="#"]:before,
li a[href^="#"] *,
li a[href^="#"] *:after,
li a[href^="#"]:after,
li a[href^="#"] *:before,
li a[href^="#"]:before,
dl a[href^="#"] *,
dl a[href^="#"] *:after,
dl a[href^="#"]:after,
dl a[href^="#"] *:before,
dl a[href^="#"]:before {
text-shadow: none; }
#breadcrumbs a[href^="#"]:visited,
figcaption a[href^="#"]:visited,
p a[href^="#"]:visited,
.page-tags a[href^="#"]:visited,
table a[href^="#"]:visited,
#crosslinks a:not(.highlight)[href^="#"]:visited,
li a[href^="#"]:visited,
dl a[href^="#"]:visited {
color: var(--text-gray); }
#breadcrumbs a[href^="#"]:hover,
figcaption a[href^="#"]:hover,
p a[href^="#"]:hover,

View File

@ -0,0 +1,39 @@
function copyPreToClipdord(btn) {
const pre = btn.parentElement.parentElement.getElementsByTagName("PRE")[0];
const range = document.createRange();
range.selectNode(pre);
window.getSelection().addRange(range);
var successful = document.execCommand('copy');
window.getSelection().removeRange(range);
}
window.addEventListener('DOMContentLoaded', () => {
const sections = document.querySelectorAll('h1[id],h2[id],h3[id],h4[id],h5[id],h6[id]');
const activate = (entry) => {
entry.classList.add('active');
if (["LI", "UL"].includes(entry.parentElement.tagName)) {
activate(entry.parentElement);
}
};
const activateLast = () => {
document.querySelectorAll('#text-table-of-contents li.active, #text-table-of-contents ul.active').forEach(a => {
a.classList.remove('active')
});
let mostRecent = { section: sections[0], bottom: -Infinity };
const windowHeight = window.innerHeight;
sections.forEach((section) => {
const bounds = section.getBoundingClientRect()
if ( bounds.bottom > mostRecent.bottom && bounds.top < windowHeight ) {
mostRecent = { section, bottom: bounds.bottom };
}
})
activate(document.querySelector(`#text-table-of-contents li a[href="#${mostRecent.section.getAttribute('id')}"]`).parentElement);
}
const observer = new IntersectionObserver(entries => {
activateLast();
});
sections.forEach((section) => {
observer.observe(section);
});
});