Org html: add copy button to src/example block
This commit is contained in:
parent
d6d608304c
commit
9ba5a35f96
31
config.org
31
config.org
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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'; }
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue