Skip to content

Commit e277a99

Browse files
committed
feat: add copy code button.
1 parent 90ba7d7 commit e277a99

File tree

4 files changed

+81
-20
lines changed

4 files changed

+81
-20
lines changed

Sources/Markdown/Resources/web.bundle/copy.js

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Sources/Markdown/Resources/web.bundle/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<link rel="stylesheet" href="marked.css">
66
<script type="text/javascript" src="./prism.js"></script>
77
<script src="./marked.min.js" type="text/javascript" charset="utf-8"></script>
8+
<script src="./copy.js" type="text/javascript"></script>
89
</head>
910
<body>
1011
<div id="__markdown_preview__" class="markdown-body"></div>

Sources/Markdown/Resources/web.bundle/main.js

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,54 @@
1-
marked.setOptions({
2-
highlight: (code, lang) => {
3-
const language = Prism.languages[lang];
4-
if (language) {
5-
return Prism.highlight(code, language, lang);
6-
}
7-
return code;
8-
},
9-
});
1+
// marked.setOptions({
2+
// highlight: (code, lang) => {
3+
// const language = Prism.languages[lang];
4+
// if (language) {
5+
// return Prism.highlight(code, language, lang);
6+
// }
7+
// return code;
8+
// },
9+
// });
1010

11-
const renderer = {
12-
listitem: (text, task, checked) => {
13-
const input = typeof checked == "boolean" ? `<input type="checkbox" disabled=""${checked ? ' checked=""' : ''} class="task-list-item-checkbox">`: '';
14-
const cls = typeof checked == "boolean" && typeof task === "boolean" ? 'class="task-list-item"' : ""
15-
return `<li ${cls}>${input} ${(text || '').replace(/^<.*?>\s/, '')}</li>`;
11+
marked.use({
12+
renderer: {
13+
code: (code, infostring, escaped) => {
14+
const language = Prism.languages[infostring];
15+
const codeHTML = language ? Prism.highlight(code, language, infostring) : code;
16+
const codeId = randomid();
17+
codeData[codeId] = code;
18+
const buttonElm = `<button type="button" class="icon copy-icon copied" onclick="copied(this, '${codeId}')">${copyElm}</button>`;
19+
return `<pre class="highlight"><code ${infostring ? `class="language-${infostring}"`: ''}>${codeHTML}</code>${buttonElm}</pre>`
20+
},
21+
listitem: (text, task, checked) => {
22+
const input = typeof checked == "boolean" ? `<input type="checkbox" disabled=""${checked ? ' checked=""' : ''} class="task-list-item-checkbox">`: '';
23+
const cls = typeof checked == "boolean" && typeof task === "boolean" ? 'class="task-list-item"' : ""
24+
return `<li ${cls}>${input} ${(text || '').replace(/^<.*?>\s/, '')}</li>`;
25+
}
1626
}
17-
}
27+
});
1828

19-
marked.use({ renderer });
29+
const copyElm = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000" height="30" width="30" role="img">
30+
<title>Copy to Clipboard</title>
31+
<path d="M704 896H64V320h640v192h64V192c0-35-29-64-64-64H512C512 57 455 0 384 0S256 57 256 128H64c-35 0-64 29-64 64v704c0 35 29 64 64 64h640c35 0 64-29 64-64V768h-64v128zM192 192h64s64-29 64-64 29-64 64-64 64 29 64 64 32 64 64 64h64s64 29 64 64H128c0-39 28-64 64-64zm-64 512h128v-64H128v64zm448-128V448L320 640l256 192V704h320V576H576zM128 832h192v-64H128v64zm320-448H128v64h320v-64zM256 512H128v64h128v-64z"/>
32+
</svg>
33+
`;
2034

2135
window.__markdown_preview_dom__ = document.getElementById('__markdown_preview__');
22-
23-
function markdownPreview(content) {
36+
const randomid = () => parseInt(String(Math.random() * 1e15), 10).toString(36);
37+
const codeData = {};
38+
const copied = (target, id) => {
39+
target.classList.add('active');
40+
copyTextToClipboard(codeData[id] || '', function() {
41+
var timer = setTimeout(() => {
42+
target.classList.remove('active');
43+
clearTimeout(timer);
44+
}, 2000);
45+
});
46+
}
47+
const markdownPreview = (content) => {
2448
__markdown_preview_dom__.innerHTML = marked.parse(content);
2549
}
2650

51+
2752
if (window.webkit) {
2853
window.webkit.messageHandlers.mdPreviewDidReady.postMessage(null);
2954
// __markdown_preview_dom__.innerHTML = JSON.stringify(typeof window.webkit.messageHandlers.mdPreviewDidReady)

Sources/Markdown/Resources/web.bundle/marked.css

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,41 @@ body, html {
1010
cursor: default;
1111
}
1212

13-
.markdown {
14-
min-height: 100%;
13+
.highlight:hover .copied {
14+
display: block;
15+
}
16+
.copy-icon.copied:hover, .copy-icon.copied.active {
17+
opacity: 1;
18+
}
19+
.copy-icon.copied.active {
20+
color: var(--color-prettylights-syntax-markup-inserted-text);
21+
}
22+
.copy-icon.copied {
23+
display: none;
24+
border-radius: 0.25rem;
25+
border: none;
26+
fill: currentColor;
27+
cursor: pointer;
28+
height: 1.25rem;
29+
-webkit-mask-size: cover;
30+
background-color: transparent;
31+
mask-size: cover;
32+
margin: 0;
33+
padding: 0.05rem;
34+
position: absolute;
35+
right: 0.5rem;
36+
top: 0.75rem;
37+
width: 1.25rem;
38+
opacity: .4;
39+
transition: all .3s;
40+
}
41+
.copy-icon.copied svg {
42+
width: 100%;
43+
height: 100%;
44+
}
45+
46+
.markdown-body .highlight {
47+
position: relative;
1548
}
1649

1750
.markdown-body pre code {

0 commit comments

Comments
 (0)