Skip to content

Commit 9634601

Browse files
authored
Merge pull request #8992 from quarto-dev/html/clipboard-in-modal
2 parents c056454 + cb903da commit 9634601

File tree

4 files changed

+48
-26
lines changed

4 files changed

+48
-26
lines changed

news/changelog-1.5.md

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ All changes included in 1.5:
66
- ([#8118](https://github.com/quarto-dev/quarto-cli/issues/8118)): Add support for `body-classes` to add classes to the document body.
77
- ([#8311](https://github.com/quarto-dev/quarto-cli/issues/8311)): Correct z-order for margins with no contents
88
- ([#8862](https://github.com/quarto-dev/quarto-cli/issues/8862)): Properly deal with an `aside` within a definition list.
9+
- ([#8990](https://github.com/quarto-dev/quarto-cli/issues/8990)): Copy button now works for embedded code source in modal window when optin-in `code-tools` feature.
910

1011
## PDF Format
1112

src/command/render/codetools.ts

+9-10
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
/*
2-
* codetools.ts
3-
*
4-
* Copyright (C) 2020-2022 Posit Software, PBC
5-
*
6-
*/
2+
* codetools.ts
3+
*
4+
* Copyright (C) 2020-2022 Posit Software, PBC
5+
*/
76

87
import { Document, Element } from "../../core/deno-dom.ts";
98
import {
@@ -32,7 +31,7 @@ const kHideAllCodeLinkId = "quarto-hide-all-code";
3231
const kShowAllCodeLinkId = "quarto-show-all-code";
3332
const kViewSourceLinkId = "quarto-view-source";
3433
const kEmbeddedSourceClass = "quarto-embedded-source-code";
35-
const kEmbeddedSourceModalId = kEmbeddedSourceClass + "-modal";
34+
export const kEmbeddedSourceModalId = kEmbeddedSourceClass + "-modal";
3635
const kEmbeddedSourceModalLabelId = kEmbeddedSourceClass + "-modal-label";
3736
const kKeepSourceSentinel = "quarto-executable-code-5450563D";
3837

@@ -56,7 +55,7 @@ export function resolveKeepSource(
5655
const codeTools = format.render?.[kCodeTools];
5756
if (
5857
codeTools === true ||
59-
(typeof (codeTools) === "object" &&
58+
(typeof codeTools === "object" &&
6059
(codeTools?.source === undefined || codeTools?.source === true))
6160
) {
6261
format.render[kKeepSource] = true;
@@ -328,17 +327,17 @@ function resolveCodeTools(format: Format, doc: Document): CodeTools {
328327
const kCodeCaption = format.language[kCodeToolsMenuCaption]!;
329328
const codeTools = format?.render[kCodeTools];
330329
const codeToolsResolved = {
331-
source: typeof (codeTools) === "boolean"
330+
source: typeof codeTools === "boolean"
332331
? codeTools
333332
: codeTools?.source !== undefined
334333
? codeTools?.source
335334
: true,
336-
toggle: typeof (codeTools) === "boolean"
335+
toggle: typeof codeTools === "boolean"
337336
? codeTools
338337
: codeTools?.toggle !== undefined
339338
? !!codeTools?.toggle
340339
: true,
341-
caption: typeof (codeTools) === "boolean"
340+
caption: typeof codeTools === "boolean"
342341
? kCodeCaption
343342
: codeTools?.caption || kCodeCaption,
344343
};

src/format/html/format-html.ts

+11-2
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,10 @@ import {
4747
SassBundle,
4848
} from "../../config/types.ts";
4949

50-
import { formatHasCodeTools } from "../../command/render/codetools.ts";
50+
import {
51+
formatHasCodeTools,
52+
kEmbeddedSourceModalId,
53+
} from "../../command/render/codetools.ts";
5154

5255
import { createHtmlFormat } from "./../formats-shared.ts";
5356

@@ -651,6 +654,9 @@ function htmlFormatPostprocessor(
651654

652655
// process all of the code blocks
653656
const codeBlocks = doc.querySelectorAll("pre.sourceCode");
657+
const EmbedSourceModal = doc.querySelector(
658+
`#${kEmbeddedSourceModalId}`,
659+
);
654660
for (let i = 0; i < codeBlocks.length; i++) {
655661
const code = codeBlocks[i] as Element;
656662

@@ -670,10 +676,13 @@ function htmlFormatPostprocessor(
670676
code.parentElement?.classList.add("hidden");
671677
}
672678

673-
// insert code copy button
679+
// insert code copy button (with specfic attribute when inside a modal)
674680
if (codeCopy) {
675681
code.classList.add("code-with-copy");
676682
const copyButton = createCodeCopyButton(doc, format);
683+
if (EmbedSourceModal && EmbedSourceModal.contains(code)) {
684+
copyButton.setAttribute("data-in-quarto-modal", "");
685+
}
677686
code.appendChild(copyButton);
678687
}
679688

src/resources/formats/html/templates/quarto-html.ejs

+27-14
Original file line numberDiff line numberDiff line change
@@ -228,20 +228,7 @@ window.document.addEventListener("DOMContentLoaded", function (event) {
228228
return false;
229229
}
230230
231-
const clipboard = new window.ClipboardJS('.code-copy-button', {
232-
text: function(trigger) {
233-
const codeEl = trigger.previousElementSibling.cloneNode(true);
234-
for (const childEl of codeEl.children) {
235-
if (isCodeAnnotation(childEl)) {
236-
childEl.remove();
237-
}
238-
}
239-
return codeEl.innerText;
240-
}
241-
});
242-
243-
244-
clipboard.on('success', function(e) {
231+
const onCopySuccess = function(e) {
245232
// button target
246233
const button = e.trigger;
247234
// don't keep focus
@@ -277,7 +264,33 @@ window.document.addEventListener("DOMContentLoaded", function (event) {
277264
}, 1000);
278265
// clear code selection
279266
e.clearSelection();
267+
}
268+
269+
const getTextToCopy = function(trigger) {
270+
const codeEl = trigger.previousElementSibling.cloneNode(true);
271+
for (const childEl of codeEl.children) {
272+
if (isCodeAnnotation(childEl)) {
273+
childEl.remove();
274+
}
275+
}
276+
return codeEl.innerText;
277+
}
278+
279+
const clipboard = new window.ClipboardJS('.code-copy-button:not([data-in-quarto-modal])', {
280+
text: getTextToCopy
280281
});
282+
clipboard.on('success', onCopySuccess);
283+
284+
285+
if (window.document.getElementById('quarto-embedded-source-code-modal')) {
286+
// For code content inside modals, clipBoardJS needs to be initialized with a container option
287+
// TODO: Check when it could be a function (https://github.com/zenorocha/clipboard.js/issues/860)
288+
const clipboardModal = new window.ClipboardJS('.code-copy-button[data-in-quarto-modal]', {
289+
text: getTextToCopy,
290+
container: window.document.getElementById('quarto-embedded-source-code-modal')
291+
});
292+
clipboardModal.on('success', onCopySuccess);
293+
}
281294
282295
<% } %>
283296

0 commit comments

Comments
 (0)