diff --git a/src/parser/copycode.ts b/src/parser/copycode.ts index 9bdfd3c..cb611b9 100644 --- a/src/parser/copycode.ts +++ b/src/parser/copycode.ts @@ -9,15 +9,20 @@ export default function copycode(md: MarkdownIt) { const defaultRender = md.renderer.rules.fence!; md.renderer.rules.fence = (tokens, idx, options, env, self) => { const renderedPreBlock = defaultRender(tokens, idx, options, env, self); + const content = tokens[idx].content; return `
${renderedPreBlock}
- +
${checkIcon} +
+
${xIcon} - +
`; diff --git a/static/colors.css b/static/colors.css index 846f6ad..a101441 100644 --- a/static/colors.css +++ b/static/colors.css @@ -19,15 +19,12 @@ --icon-file: var(--text-secondary); --icon-back: var(--text-secondary); - /* Code Copy Icons */ - --icon-copy-fg: #aaa; - --icon-copy-bg: #333; - --icon-check-fg: #ddffcc; - --icon-check-bg: #5c993d; - --icon-x-fg: #ffcccc; - --icon-x-bg: #993d3d; - --copy-button-fg: var(--icon-copy-fg) - --copy-button-bg: var(--icon-copy-bg) + --copy-button-fg: #aaa; + --copy-button-bg: #333; + --copy-success-fg: #ddffcc; + --copy-success-bg: #5c993d; + --copy-fail-fg: #ffcccc; + --copy-fail-bg: #993d3d; --syntax-text: var(--text-primary); --syntax-keyword: #aed7ff; @@ -79,15 +76,12 @@ --icon-file: #636c76; --icon-back: var(--text-secondary); - /* Code Copy Icons */ - --icon-copy-fg: #1f2328; - --icon-copy-bg: #e7e9eb; - --icon-check-fg: #154000; - --icon-check-bg: #c7e6b8; - --icon-x-fg: #400000; - --icon-x-bg: #e6b8b8; - --copy-button-fg: var(--icon-copy-fg) - --copy-button-bg: var(--icon-copy-bg) + --copy-button-fg: #1f2328; + --copy-button-bg: #e7e9eb; + --copy-success-fg: #154000; + --copy-success-bg: #c7e6b8; + --copy-fail-fg: #400000; + --copy-fail-bg: #e6b8b8; /* source for light mode syntax theme: * https://github.com/highlightjs/highlight.js/blob/main/src/styles/github.css diff --git a/static/copycode/client.js b/static/copycode/client.js index 3bc27f9..bb0080f 100644 --- a/static/copycode/client.js +++ b/static/copycode/client.js @@ -1,72 +1,26 @@ -let clipboard = new ClipboardJS('.copy-button'); +document.querySelectorAll('.copy-success, .copy-fail').forEach((element) => { + element.style.display = 'none'; +}); -// Setup copy button icons -const Icons = { - Copy: { - Class: 'icon-copy', - ForegroundColor: '', - BackgroundColor: '', - }, - Success: { - Class: 'icon-check', - ForegroundColor: '', - BackgroundColor: '', - }, - Fail: { - Class: 'icon-x', - ForegroundColor: '', - BackgroundColor: '', - }, +const Notify = { + Success: '.copy-success', + Fail: '.copy-fail', }; -resetButtons(); -window.matchMedia('(prefers-color-scheme: light)').addEventListener('change', resetButtons); -function resetButtons() { - getIconColors(); - document.querySelectorAll('.copy-button').forEach((btn) => { - setIcon(btn, Icons.Copy); - }); -} - -// Get icon color values from css -function getIconColors() { - console.log('getting colors'); - let element = window.getComputedStyle(document.documentElement); - Object.entries(Icons).forEach(([, icon]) => { - icon.ForegroundColor = element.getPropertyValue(`--${icon.Class}-fg`); - icon.BackgroundColor = element.getPropertyValue(`--${icon.Class}-bg`); - }); -} - -function setIcon(btn, icon) { - for (let child of btn.children) { - console.log(child.classList.contains(icon.Class)); - if (child.classList.contains(icon.Class)) { - child.style.display = 'inline-block'; - btn.style.setProperty('--copy-button-fg', icon.ForegroundColor); - btn.style.setProperty('--copy-button-bg', icon.BackgroundColor); - } else { - child.style.display = 'none'; - } - } -} +let clipboard = new ClipboardJS('.copy-button'); -//TODO: Implement success callback clipboard.on('success', function (e) { - console.info('Trigger:', e.trigger); - const btn = e.trigger; - - console.info(Icons); - - setIcon(btn, Icons.Success); - - setTimeout(() => { - setIcon(btn, Icons.Copy); - }, 2000); + showNotification(e.trigger, Notify.Success); }); -//TODO: Implement failure callback clipboard.on('error', function (e) { - console.log('Copy failed!'); - console.error('Trigger:', e.trigger); + showNotification(e.trigger, Notify.Fail); }); + +function showNotification(btn, notify) { + const notificationElement = btn.parentElement.querySelector(notify); + notificationElement.style.display = 'flex'; + setTimeout(() => { + notificationElement.style.display = 'none'; + }, 2000); +} diff --git a/static/markdown.css b/static/markdown.css index 0ad7cca..0587506 100644 --- a/static/markdown.css +++ b/static/markdown.css @@ -188,24 +188,41 @@ blockquote { top: 0.5rem; right: 0.5rem; } -.copy-button { +.copy-button, .copy-success, .copy-fail { + position: absolute; + top: 0; + right: 0; + display: flex; + align-items: center; + justify-content: center; + height: 2rem; + width: 2rem; padding: 0.4rem; border: 0; border-radius: 0.4rem; background: none; fill: var(--copy-button-fg); - opacity: 0; - outline: none; cursor: pointer; transition: opacity 0.2s, background 0.2s; } -pre:hover + .copy-wrapper .copy-button { +.copy-button { + opacity: 0; +} +pre:hover + .copy-wrapper > .copy-button { opacity: 0.3; } .copy-button:hover { opacity: 1; background-color: var(--copy-button-bg); } +.copy-success { + background: var(--copy-success-bg); + fill: var(--copy-success-fg); +} +.copy-fail { + background: var(--copy-fail-bg); + fill: var(--copy-fail-fg); +} /* -------------------------------------------------------------------------- * MISCELLANEOUS ------------------------------------------------------------ */