From b0b62d67ed243e8916358b81e420f1939781f863 Mon Sep 17 00:00:00 2001 From: Rodrigo Pombo Date: Tue, 3 May 2022 15:12:39 +0000 Subject: [PATCH 1/8] Copy button component --- packages/mdx/dev/content/copy-button.mdx | 39 +++++++++++ packages/mdx/src/mini-editor/editor-shift.tsx | 13 ++++ packages/mdx/src/mini-editor/editor-tween.tsx | 10 ++- packages/mdx/src/smooth-code/copy-button.tsx | 69 +++++++++++++++++++ packages/mdx/src/utils/code.ts | 8 +++ 5 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 packages/mdx/dev/content/copy-button.mdx create mode 100644 packages/mdx/src/smooth-code/copy-button.tsx diff --git a/packages/mdx/dev/content/copy-button.mdx b/packages/mdx/dev/content/copy-button.mdx new file mode 100644 index 00000000..4f03fd03 --- /dev/null +++ b/packages/mdx/dev/content/copy-button.mdx @@ -0,0 +1,39 @@ +one line: + +```js +const x = 2 +``` + +no editor: + +```js +function foo() { + return 2 +} +``` + +one file editor: + +```js foo.js +function foo() { + return 2 +} +``` + +two files: + + + +```js foo.js +function foo() { + return 2 +} +``` + +```js bar.js +function bar() { + return 2 +} +``` + + diff --git a/packages/mdx/src/mini-editor/editor-shift.tsx b/packages/mdx/src/mini-editor/editor-shift.tsx index 9c2f92d0..0b7b8c18 100644 --- a/packages/mdx/src/mini-editor/editor-shift.tsx +++ b/packages/mdx/src/mini-editor/editor-shift.tsx @@ -4,6 +4,7 @@ import { CodeStep, } from "../smooth-code" import React from "react" +import { codeToText } from "utils" export type CodeFile = CodeStep & { name: string @@ -37,6 +38,8 @@ type OutputPanel = { type Transition = { northPanel: OutputPanel southPanel?: OutputPanel | null + northContent: string + southContent: string } type TabsSnapshot = Record< @@ -110,6 +113,7 @@ export function useTransition( ) return { + northContent: getContentFromFile(nextNorthFile), northPanel: { tabs: northTabs, style: northStyle, @@ -126,6 +130,7 @@ export function useTransition( /> ), }, + southContent: getContentFromFile(nextSouthFile), southPanel: inputSouthPanel && { tabs: southTabs!, style: southStyle!, @@ -162,6 +167,7 @@ function startingPosition( } = getStepFiles(prev, next, true) return { + northContent: getContentFromFile(prevNorthFile), northPanel: { tabs: inputNorthPanel.tabs.map(title => ({ title, @@ -182,6 +188,7 @@ function startingPosition( /> ), }, + southContent: getContentFromFile(prevSouthFile), southPanel: inputSouthPanel && { tabs: inputSouthPanel.tabs.map(title => ({ title, @@ -229,6 +236,7 @@ function endingPosition( } return { + northContent: getContentFromFile(nextNorthFile), northPanel: { tabs: inputNorthPanel.tabs.map(title => ({ title, @@ -249,6 +257,7 @@ function endingPosition( /> ), }, + southContent: getContentFromFile(nextSouthFile), southPanel: inputSouthPanel && { tabs: inputSouthPanel.tabs.map(title => ({ title, @@ -305,6 +314,10 @@ function CodeTransition({ ) } +function getContentFromFile(file?: CodeFile) { + return file ? codeToText(file.code) : "" +} + /** * Get the StepFiles for a transition * in each panel, if the prev and next active files are the same diff --git a/packages/mdx/src/mini-editor/editor-tween.tsx b/packages/mdx/src/mini-editor/editor-tween.tsx index 8f2add33..9729a77d 100644 --- a/packages/mdx/src/mini-editor/editor-tween.tsx +++ b/packages/mdx/src/mini-editor/editor-tween.tsx @@ -7,6 +7,7 @@ import { TerminalPanel } from "./terminal-panel" import { useTransition, EditorStep } from "./editor-shift" import { CodeConfig } from "../smooth-code" import { useLayoutEffect } from "../utils" +import { CopyButton } from "smooth-code/copy-button" export { EditorTransition, EditorTween } export type { EditorTransitionProps, EditorTweenProps } @@ -53,7 +54,12 @@ function EditorTween({ ...divProps }: EditorTweenProps) { const ref = React.createRef() - const { northPanel, southPanel } = useTransition( + const { + northPanel, + southPanel, + northContent, + southContent, + } = useTransition( ref, prev, next || prev, @@ -102,6 +108,8 @@ function EditorTween({ southPanel={southPanel} terminalPanel={terminalPanel} theme={codeConfig.theme} + // TODO same for south + button={} /> ) } diff --git a/packages/mdx/src/smooth-code/copy-button.tsx b/packages/mdx/src/smooth-code/copy-button.tsx new file mode 100644 index 00000000..52686075 --- /dev/null +++ b/packages/mdx/src/smooth-code/copy-button.tsx @@ -0,0 +1,69 @@ +export function CopyButton({ + content, +}: { + content: string +}) { + return ( + copyToClipboard(content)} + fill="none" + stroke="currentColor" + viewBox="0 0 24 24" + xmlns="http://www.w3.org/2000/svg" + > + + + ) +} + +function copyToClipboard(text: string) { + if (!navigator.clipboard) { + fallbackCopyTextToClipboard(text) + return + } + navigator.clipboard.writeText(text).then( + function () { + console.log( + "Async: Copying to clipboard was successful!" + ) + }, + function (err) { + console.error("Async: Could not copy text: ", err) + } + ) +} + +function fallbackCopyTextToClipboard(text: string) { + var textArea = document.createElement("textarea") + textArea.value = text + + // Avoid scrolling to bottom + textArea.style.top = "0" + textArea.style.left = "0" + textArea.style.position = "fixed" + + document.body.appendChild(textArea) + textArea.focus() + textArea.select() + + try { + var successful = document.execCommand("copy") + var msg = successful ? "successful" : "unsuccessful" + console.log("Fallback: Copying text command was " + msg) + } catch (err) { + console.error("Fallback: Oops, unable to copy", err) + } + + document.body.removeChild(textArea) +} diff --git a/packages/mdx/src/utils/code.ts b/packages/mdx/src/utils/code.ts index 6522ccf1..f98cc73a 100644 --- a/packages/mdx/src/utils/code.ts +++ b/packages/mdx/src/utils/code.ts @@ -11,3 +11,11 @@ export type Code = { lines: HighlightedLine[] lang: string } + +export function codeToText(code: Code) { + return code.lines + .map(line => + line.tokens.map(token => token.content).join("") + ) + .join("\n") +} From 967d59bae3dd30922a4ff5e74008546c86417ed5 Mon Sep 17 00:00:00 2001 From: Rodrigo Pombo Date: Wed, 4 May 2022 13:50:13 +0200 Subject: [PATCH 2/8] Add button to south panel --- packages/mdx/dev/content/copy-button.mdx | 20 +++++++++++++++++++ packages/mdx/src/mini-editor/editor-frame.tsx | 9 ++++++--- packages/mdx/src/mini-editor/editor-tween.tsx | 4 ++-- packages/mdx/src/smooth-code/copy-button.tsx | 1 + 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/packages/mdx/dev/content/copy-button.mdx b/packages/mdx/dev/content/copy-button.mdx index 4f03fd03..807108a6 100644 --- a/packages/mdx/dev/content/copy-button.mdx +++ b/packages/mdx/dev/content/copy-button.mdx @@ -37,3 +37,23 @@ function bar() { ``` + +two panels: + + + +```js foo.js +function foo() { + return 2 +} +``` + +--- + +```js bar.js +function bar() { + return 2 +} +``` + + diff --git a/packages/mdx/src/mini-editor/editor-frame.tsx b/packages/mdx/src/mini-editor/editor-frame.tsx index 409788f9..e9525ef2 100644 --- a/packages/mdx/src/mini-editor/editor-frame.tsx +++ b/packages/mdx/src/mini-editor/editor-frame.tsx @@ -30,7 +30,8 @@ type EditorFrameProps = { theme: EditorTheme terminalPanel?: React.ReactNode height?: number - button?: React.ReactNode + northButton?: React.ReactNode + southButton?: React.ReactNode classes?: Classes onTabClick?: (filename: string) => void } & React.PropsWithoutRef @@ -45,7 +46,8 @@ export const EditorFrame = React.forwardRef< terminalPanel, style, height, - button, + northButton, + southButton, theme, className, onTabClick, @@ -70,7 +72,7 @@ export const EditorFrame = React.forwardRef< } + northButton={} + southButton={} /> ) } diff --git a/packages/mdx/src/smooth-code/copy-button.tsx b/packages/mdx/src/smooth-code/copy-button.tsx index 52686075..87c1fa35 100644 --- a/packages/mdx/src/smooth-code/copy-button.tsx +++ b/packages/mdx/src/smooth-code/copy-button.tsx @@ -17,6 +17,7 @@ export function CopyButton({ viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" > + Copy Date: Wed, 4 May 2022 14:04:58 +0200 Subject: [PATCH 3/8] Add copy feedback --- packages/mdx/dev/files.ts | 2 +- packages/mdx/src/smooth-code/copy-button.tsx | 52 ++++++++++++-------- 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/packages/mdx/dev/files.ts b/packages/mdx/dev/files.ts index 29a2479d..a8c07650 100644 --- a/packages/mdx/dev/files.ts +++ b/packages/mdx/dev/files.ts @@ -1,7 +1,7 @@ import fs from "fs" import { remarkCodeHike } from "../src/index" import { compile } from "@mdx-js/mdx" -import theme from "shiki/themes/nord.json" +import theme from "shiki/themes/slack-ochin.json" import { withDebugger } from "mdx-debugger" export async function getFiles() { diff --git a/packages/mdx/src/smooth-code/copy-button.tsx b/packages/mdx/src/smooth-code/copy-button.tsx index 87c1fa35..0f8446b2 100644 --- a/packages/mdx/src/smooth-code/copy-button.tsx +++ b/packages/mdx/src/smooth-code/copy-button.tsx @@ -1,8 +1,12 @@ +import React from "react" + export function CopyButton({ content, }: { content: string }) { + const [copied, setCopied] = React.useState(false) + return ( copyToClipboard(content)} + onClick={() => { + copyToClipboard(content) + setCopied(true) + setTimeout(() => { + setCopied(false) + }, 1200) + }} + className="ch-copy-button" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" > Copy - + + {copied ? ( + + ) : ( + + )} ) } @@ -33,16 +54,7 @@ function copyToClipboard(text: string) { fallbackCopyTextToClipboard(text) return } - navigator.clipboard.writeText(text).then( - function () { - console.log( - "Async: Copying to clipboard was successful!" - ) - }, - function (err) { - console.error("Async: Could not copy text: ", err) - } - ) + navigator.clipboard.writeText(text) } function fallbackCopyTextToClipboard(text: string) { @@ -60,10 +72,10 @@ function fallbackCopyTextToClipboard(text: string) { try { var successful = document.execCommand("copy") - var msg = successful ? "successful" : "unsuccessful" - console.log("Fallback: Copying text command was " + msg) + // var msg = successful ? "successful" : "unsuccessful" + // console.log("Fallback: Copying text command was " + msg) } catch (err) { - console.error("Fallback: Oops, unable to copy", err) + // console.error("Fallback: Oops, unable to copy", err) } document.body.removeChild(textArea) From ab8463ed2e976bdf290e7d5d231e232f98c4ca7e Mon Sep 17 00:00:00 2001 From: Rodrigo Pombo Date: Wed, 4 May 2022 16:21:43 +0200 Subject: [PATCH 4/8] Add themes test --- packages/mdx/dev/files.ts | 9 ++-- packages/mdx/dev/layout.tsx | 73 ++++++++++++++++++++++++++++ packages/mdx/package.json | 1 + packages/mdx/pages/[name].tsx | 64 ++----------------------- packages/mdx/pages/compile.tsx | 37 --------------- packages/mdx/pages/evaluate.tsx | 45 ------------------ packages/mdx/pages/themes.tsx | 84 +++++++++++++++++++++++++++++++++ yarn.lock | 68 +++++++++++++++++++++++++- 8 files changed, 235 insertions(+), 146 deletions(-) create mode 100644 packages/mdx/dev/layout.tsx delete mode 100644 packages/mdx/pages/compile.tsx delete mode 100644 packages/mdx/pages/evaluate.tsx create mode 100644 packages/mdx/pages/themes.tsx diff --git a/packages/mdx/dev/files.ts b/packages/mdx/dev/files.ts index a8c07650..cc459413 100644 --- a/packages/mdx/dev/files.ts +++ b/packages/mdx/dev/files.ts @@ -1,7 +1,7 @@ import fs from "fs" import { remarkCodeHike } from "../src/index" import { compile } from "@mdx-js/mdx" -import theme from "shiki/themes/slack-ochin.json" +import theme from "shiki/themes/github-light.json" import { withDebugger } from "mdx-debugger" export async function getFiles() { @@ -19,7 +19,7 @@ export async function getContent(filename: string) { return file } -export async function getCode(file: string) { +export async function getCode(file: string, config = {}) { let debugLink = "" const debugCompile = withDebugger(compile, { @@ -32,7 +32,10 @@ export async function getCode(file: string) { await debugCompile(file, { outputFormat: "function-body", remarkPlugins: [ - [remarkCodeHike, { autoImport: false, theme }], + [ + remarkCodeHike, + { autoImport: false, theme, ...config }, + ], ], }) ) diff --git a/packages/mdx/dev/layout.tsx b/packages/mdx/dev/layout.tsx new file mode 100644 index 00000000..17477c11 --- /dev/null +++ b/packages/mdx/dev/layout.tsx @@ -0,0 +1,73 @@ +import Link from "next/link" +import Head from "next/head" + +const extraItems = ["themes"] + +export function Layout({ + children, + current, + contentFileNames, + style = {}, +}) { + return ( +
+ + Code Hike Test - {current} + + + +
+ {children} +
+
+ ) +} + +function Sidebar({ contentFileNames, current }) { + const items = contentFileNames.concat(extraItems) + return ( + + ) +} diff --git a/packages/mdx/package.json b/packages/mdx/package.json index e961fbaa..6b1b2fea 100644 --- a/packages/mdx/package.json +++ b/packages/mdx/package.json @@ -59,6 +59,7 @@ "@types/node-fetch": "^2.6.1", "@types/react": "^17.0.39", "autoprefixer": "^9.8.2", + "click-to-react-component": "^1.0.8", "cssnano": "^4.1.10", "diff": "^4.0.2", "esbuild": "^0.13.2", diff --git a/packages/mdx/pages/[name].tsx b/packages/mdx/pages/[name].tsx index ae4c52be..caf7b48e 100644 --- a/packages/mdx/pages/[name].tsx +++ b/packages/mdx/pages/[name].tsx @@ -1,9 +1,9 @@ import { runSync } from "@mdx-js/mdx" import * as runtime from "react/jsx-runtime.js" import { CH } from "../src/components" -import Link from "next/link" import { getCode, getContent, getFiles } from "../dev/files" -import Head from "next/head" +import { ClickToComponent } from "click-to-react-component" +import { Layout } from "../dev/layout" export async function getStaticPaths() { const files = await getFiles() @@ -37,63 +37,7 @@ export default function Page({ }) { const { default: Content } = runSync(code, runtime) return ( -
- - Code Hike Test - {current} - - - -
- ) -} - -function Sidebar({ tests, current }) { - return ( - - ) -} - -function Result({ Content, debugLink }) { - return ( -
+ -
+ ) } diff --git a/packages/mdx/pages/compile.tsx b/packages/mdx/pages/compile.tsx deleted file mode 100644 index e4002fc0..00000000 --- a/packages/mdx/pages/compile.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { compile } from "@mdx-js/mdx" -import { runSync } from "@mdx-js/mdx" -import * as runtime from "react/jsx-runtime.js" -import { remarkCodeHike } from "../src/index" -import { CH } from "../src/components" -import fs from "node:fs" - -export async function getServerSideProps() { - const source = fs.readFileSync( - "./tests/scrollycoding.mdx", - "utf8" - ) - const code = String( - await compile(source, { - outputFormat: "function-body", - remarkPlugins: [ - [remarkCodeHike, { autoImport: false }], - ], - }) - ) - return { - props: { - title: "Home", - code, - }, - } -} - -export default function Page({ title, code }) { - const { default: Content } = runSync(code, runtime) - return ( -
-

{title}

- -
- ) -} diff --git a/packages/mdx/pages/evaluate.tsx b/packages/mdx/pages/evaluate.tsx deleted file mode 100644 index 76ca7825..00000000 --- a/packages/mdx/pages/evaluate.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import { compile } from "@mdx-js/mdx" -import { runSync, evaluateSync } from "@mdx-js/mdx" -import * as runtime from "react/jsx-runtime.js" -import { remarkCodeHike } from "../src/index" -import { CH } from "../src/components" -import fs from "node:fs" - -export async function getServerSideProps() { - const source = fs.readFileSync( - "./tests/scrollycoding.mdx", - "utf8" - ) - const code = String( - await compile(source, { - outputFormat: "function-body", - remarkPlugins: [ - [remarkCodeHike, { autoImport: false }], - ], - }) - ) - return { - props: { - title: "Home", - source, - code, - }, - } -} - -export default function Page({ title, code, source }) { - // const { default: Content } = evaluateSync(source, { - // ...runtime, - // remarkPlugins: [ - // [remarkCodeHike, { autoImport: false }], - // ], - // } as any) - - const { default: Content } = runSync(code, runtime) - return ( -
-

{title}

- -
- ) -} diff --git a/packages/mdx/pages/themes.tsx b/packages/mdx/pages/themes.tsx new file mode 100644 index 00000000..aab2b707 --- /dev/null +++ b/packages/mdx/pages/themes.tsx @@ -0,0 +1,84 @@ +import { BUNDLED_THEMES } from "shiki" +import { getCode, getFiles } from "../dev/files" +import * as runtime from "react/jsx-runtime.js" +import { runSync } from "@mdx-js/mdx" +import { CH } from "../src/components" +import { Layout } from "../dev/layout" + +const mdx = ` + + +~~~js foo.js +function foo(x = 1) { + return "bar" +} +~~~ +--- +~~~css foo.css +body { + height: 32px; +} +~~~ + + +~~~py +def foo(x = 1): + return "bar" +~~~ +` + +export async function getStaticProps() { + const files = await getFiles() + const promises = BUNDLED_THEMES.filter( + x => x !== "css-variables" + ).map(async themeName => { + const theme = ( + await import(`shiki/themes/${themeName}.json`) + ).default + const { code } = await getCode(mdx, { + theme, + lineNumbers: true, + }) + return { themeName, code } + }) + + const codes = await Promise.all(promises) + + return { + props: { + tests: files, + codes, + }, + } +} + +export default function Page({ codes, tests }) { + const components = codes.map(({ code }) => { + return runSync(code, runtime).default + }) + return ( + +
+ {components.map((Content, i) => ( +
+

{codes[i].themeName}

+ +
+ ))} +
+
+ ) +} diff --git a/yarn.lock b/yarn.lock index b7d27789..6bf227c5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1925,6 +1925,36 @@ resolved "https://registry.yarnpkg.com/@fal-works/esbuild-plugin-global-externals/-/esbuild-plugin-global-externals-2.1.2.tgz#c05ed35ad82df8e6ac616c68b92c2282bd083ba4" integrity sha512-cEee/Z+I12mZcFJshKcCqC8tuX5hG3s+d+9nZ3LabqKF1vKdF41B92pJVCBggjAGORAeOzyyDDKrZwIkLffeOQ== +"@floating-ui/core@^0.6.2": + version "0.6.2" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-0.6.2.tgz#f2813f0e5f3d5ed7af5029e1a082203dadf02b7d" + integrity sha512-jktYRmZwmau63adUG3GKOAVCofBXkk55S/zQ94XOorAHhwqFIOFAy1rSp2N0Wp6/tGbe9V3u/ExlGZypyY17rg== + +"@floating-ui/dom@^0.4.5": + version "0.4.5" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-0.4.5.tgz#2e88d16646119cc67d44683f75ee99840475bbfa" + integrity sha512-b+prvQgJt8pieaKYMSJBXHxX/DYwdLsAWxKYqnO5dO2V4oo/TYBZJAUQCVNjTWWsrs6o4VDrNcP9+E70HAhJdw== + dependencies: + "@floating-ui/core" "^0.6.2" + +"@floating-ui/react-dom-interactions@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@floating-ui/react-dom-interactions/-/react-dom-interactions-0.3.1.tgz#abc0cb4b18e6f095397e50f9846572eee4e34554" + integrity sha512-tP2KEh7EHJr5hokSBHcPGojb+AorDNUf0NYfZGg/M+FsMvCOOsSEeEF0O1NDfETIzDnpbHnCs0DuvCFhSMSStg== + dependencies: + "@floating-ui/react-dom" "^0.6.3" + aria-hidden "^1.1.3" + point-in-polygon "^1.1.0" + use-isomorphic-layout-effect "^1.1.1" + +"@floating-ui/react-dom@^0.6.3": + version "0.6.3" + resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-0.6.3.tgz#7b64cfd4fd12e4a0515dbf1b2be16e48c9a06c5a" + integrity sha512-hC+pS5D6AgS2wWjbmSQ6UR6Kpy+drvWGJIri6e1EDGADTPsCaa4KzCgmCczHrQeInx9tqs81EyDmbKJYY2swKg== + dependencies: + "@floating-ui/dom" "^0.4.5" + use-isomorphic-layout-effect "^1.1.1" + "@gar/promisify@^1.0.1": version "1.1.3" resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" @@ -4445,6 +4475,13 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== +aria-hidden@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.1.3.tgz#bb48de18dc84787a3c6eee113709c473c64ec254" + integrity sha512-RhVWFtKH5BiGMycI72q2RAFMLQi8JP9bLuQXgR5a8Znp7P5KOIADSJeyfI8PCVxLEp067B2HbP5JIiI/PXIZeA== + dependencies: + tslib "^1.0.0" + array-back@^3.0.1, array-back@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0" @@ -5343,6 +5380,15 @@ cli-width@^3.0.0: resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== +click-to-react-component@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/click-to-react-component/-/click-to-react-component-1.0.8.tgz#bcad2f4551dde67c54cec77e02791c7ecda50e5a" + integrity sha512-YBNYOp00udy+NBEnUmM/3Df0Yco1iHNQ8k0ltlJVcDYK9AuYt14xPoJicBh/BokLqbzkci1p+pbdY5r4JXZC4g== + dependencies: + "@floating-ui/react-dom-interactions" "^0.3.1" + htm "^3.1.0" + react-merge-refs "^1.1.0" + clipanion@^3.2.0-rc.10: version "3.2.0-rc.11" resolved "https://registry.yarnpkg.com/clipanion/-/clipanion-3.2.0-rc.11.tgz#765661c9aeda8ecc14035a61a4b19b361f9a5400" @@ -8896,6 +8942,11 @@ hsla-regex@^1.0.0: resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38" integrity sha1-wc56MWjIxmFAM6S194d/OyJfnDg= +htm@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/htm/-/htm-3.1.1.tgz#49266582be0dc66ed2235d5ea892307cc0c24b78" + integrity sha512-983Vyg8NwUE7JkZ6NmOqpCZ+sh1bKv2iYTlUkzlWmA5JD2acKoxd4KVxbMmxX/85mtfdnDmTFoNKcg5DGAvxNQ== + html-entities@^2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.3.tgz#117d7626bece327fc8baace8868fa6f5ef856e46" @@ -12478,6 +12529,11 @@ pkg-up@^3.1.0: dependencies: find-up "^3.0.0" +point-in-polygon@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/point-in-polygon/-/point-in-polygon-1.1.0.tgz#b0af2616c01bdee341cbf2894df643387ca03357" + integrity sha512-3ojrFwjnnw8Q9242TzgXuTD+eKiutbzyslcq1ydfu82Db2y+Ogbmyrkpv0Hgj31qwT3lbS9+QAAO/pIQM35XRw== + portfinder@^1.0.28: version "1.0.28" resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778" @@ -13537,6 +13593,11 @@ react-loadable-ssr-addon-v5-slorber@^1.0.1: dependencies: "@babel/runtime" "^7.10.3" +react-merge-refs@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/react-merge-refs/-/react-merge-refs-1.1.0.tgz#73d88b892c6c68cbb7a66e0800faa374f4c38b06" + integrity sha512-alTKsjEL0dKH/ru1Iyn7vliS2QRcBp9zZPGoWxUOvRGWPUYgjo+V01is7p04It6KhgrzhJGnIj9GgX8W4bZoCQ== + react-refresh@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.11.0.tgz#77198b944733f0f1f1a90e791de4541f9f074046" @@ -15551,7 +15612,7 @@ tslib@2.1.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a" integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A== -tslib@^1.14.1, tslib@^1.9.0: +tslib@^1.0.0, tslib@^1.14.1, tslib@^1.9.0: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== @@ -16058,6 +16119,11 @@ use-isomorphic-layout-effect@^1.0.0: resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.1.tgz#7bb6589170cd2987a152042f9084f9effb75c225" integrity sha512-L7Evj8FGcwo/wpbv/qvSfrkHFtOpCzvM5yl2KVyDJoylVuSvzphiiasmjgQPttIGBAy2WKiBNR98q8w7PiNgKQ== +use-isomorphic-layout-effect@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz#497cefb13d863d687b08477d9e5a164ad8c1a6fb" + integrity sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA== + use-latest@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/use-latest/-/use-latest-1.2.0.tgz#a44f6572b8288e0972ec411bdd0840ada366f232" From 609f211c9b5d52459898ea1bcb2cef98ec3b8fca Mon Sep 17 00:00:00 2001 From: Rodrigo Pombo Date: Wed, 4 May 2022 16:43:54 +0200 Subject: [PATCH 5/8] Fix button color --- packages/mdx/src/mini-editor/editor-frame.tsx | 11 ++++++++++- packages/mdx/src/utils/theme.ts | 10 ++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/packages/mdx/src/mini-editor/editor-frame.tsx b/packages/mdx/src/mini-editor/editor-frame.tsx index e9525ef2..cb2c4a60 100644 --- a/packages/mdx/src/mini-editor/editor-frame.tsx +++ b/packages/mdx/src/mini-editor/editor-frame.tsx @@ -68,7 +68,12 @@ export const EditorFrame = React.forwardRef< ...style, }} > -
+
Date: Wed, 4 May 2022 18:08:14 +0200 Subject: [PATCH 6/8] Add codeblock button --- packages/mdx/pages/themes.tsx | 2 +- packages/mdx/src/mdx-client/code.tsx | 5 ++++- packages/mdx/src/mini-editor/editor-tween.tsx | 18 ++++++++++++++++-- packages/mdx/src/smooth-code/code-tween.tsx | 17 +++++++++++++++++ packages/mdx/src/smooth-code/copy-button.tsx | 4 +++- 5 files changed, 41 insertions(+), 5 deletions(-) diff --git a/packages/mdx/pages/themes.tsx b/packages/mdx/pages/themes.tsx index aab2b707..7ab59df6 100644 --- a/packages/mdx/pages/themes.tsx +++ b/packages/mdx/pages/themes.tsx @@ -58,7 +58,7 @@ export default function Page({ codes, tests }) { }) return ( diff --git a/packages/mdx/src/mdx-client/code.tsx b/packages/mdx/src/mdx-client/code.tsx index f0326cae..00bdd665 100644 --- a/packages/mdx/src/mdx-client/code.tsx +++ b/packages/mdx/src/mdx-client/code.tsx @@ -32,7 +32,10 @@ export function InnerCode({
diff --git a/packages/mdx/src/mini-editor/editor-tween.tsx b/packages/mdx/src/mini-editor/editor-tween.tsx index 3cab5019..8d128c1d 100644 --- a/packages/mdx/src/mini-editor/editor-tween.tsx +++ b/packages/mdx/src/mini-editor/editor-tween.tsx @@ -108,8 +108,22 @@ function EditorTween({ southPanel={southPanel} terminalPanel={terminalPanel} theme={codeConfig.theme} - northButton={} - southButton={} + northButton={ + + } + southButton={ + + } /> ) } diff --git a/packages/mdx/src/smooth-code/code-tween.tsx b/packages/mdx/src/smooth-code/code-tween.tsx index 4aa3c0f0..fd0e7271 100644 --- a/packages/mdx/src/smooth-code/code-tween.tsx +++ b/packages/mdx/src/smooth-code/code-tween.tsx @@ -17,6 +17,7 @@ import { CodeShift, } from "./partial-step-parser" import { SmoothLines } from "./smooth-lines" +import { CopyButton } from "./copy-button" type HTMLProps = React.DetailedHTMLProps< React.HTMLAttributes, @@ -43,6 +44,7 @@ export type CodeConfig = { horizontalCenter?: boolean theme: IRawTheme lineNumbers?: boolean + showCopyButton?: boolean } function useCodeShift({ @@ -132,6 +134,7 @@ function AfterDimensions({ stepInfo, progress, htmlProps, + config, }: { dimensions: NonNullable stepInfo: CodeShift @@ -140,6 +143,7 @@ function AfterDimensions({ htmlProps: HTMLProps }) { const { bg, fg } = getCodeColors(theme) + return ( + {config.showCopyButton ? ( + + ) : undefined} ) } @@ -183,6 +199,7 @@ function Wrapper({ style={{ margin: 0, padding: 0, + position: "relative", // using this instead of
 because https://github.com/code-hike/codehike/issues/120
         whiteSpace: "pre",
         ...style,
diff --git a/packages/mdx/src/smooth-code/copy-button.tsx b/packages/mdx/src/smooth-code/copy-button.tsx
index 0f8446b2..7209907c 100644
--- a/packages/mdx/src/smooth-code/copy-button.tsx
+++ b/packages/mdx/src/smooth-code/copy-button.tsx
@@ -2,8 +2,10 @@ import React from "react"
 
 export function CopyButton({
   content,
+  style,
 }: {
   content: string
+  style?: React.CSSProperties
 }) {
   const [copied, setCopied] = React.useState(false)
 
@@ -12,8 +14,8 @@ export function CopyButton({
       style={{
         width: "1.5em",
         height: "1.5em",
-        margin: "0 0.8em",
         cursor: "pointer",
+        ...style,
       }}
       onClick={() => {
         copyToClipboard(content)

From 0b106c22fc743b6569bd85443a535ea3d03c0095 Mon Sep 17 00:00:00 2001
From: Rodrigo Pombo 
Date: Wed, 4 May 2022 18:34:48 +0200
Subject: [PATCH 7/8] Add copy button to config

---
 packages/mdx/dev/files.ts                     |  7 ++++-
 packages/mdx/pages/themes.tsx                 |  1 +
 packages/mdx/src/mdx-client/code.tsx          |  5 +---
 packages/mdx/src/mdx-plugin/plugin.ts         |  1 +
 packages/mdx/src/mini-editor/editor-tween.tsx | 28 ++++++++++---------
 5 files changed, 24 insertions(+), 18 deletions(-)

diff --git a/packages/mdx/dev/files.ts b/packages/mdx/dev/files.ts
index cc459413..626effcf 100644
--- a/packages/mdx/dev/files.ts
+++ b/packages/mdx/dev/files.ts
@@ -34,7 +34,12 @@ export async function getCode(file: string, config = {}) {
       remarkPlugins: [
         [
           remarkCodeHike,
-          { autoImport: false, theme, ...config },
+          {
+            autoImport: false,
+            showCopyButton: true,
+            theme,
+            ...config,
+          },
         ],
       ],
     })
diff --git a/packages/mdx/pages/themes.tsx b/packages/mdx/pages/themes.tsx
index 7ab59df6..848f34c0 100644
--- a/packages/mdx/pages/themes.tsx
+++ b/packages/mdx/pages/themes.tsx
@@ -38,6 +38,7 @@ export async function getStaticProps() {
     const { code } = await getCode(mdx, {
       theme,
       lineNumbers: true,
+      showCopyButton: true,
     })
     return { themeName, code }
   })
diff --git a/packages/mdx/src/mdx-client/code.tsx b/packages/mdx/src/mdx-client/code.tsx
index 00bdd665..f0326cae 100644
--- a/packages/mdx/src/mdx-client/code.tsx
+++ b/packages/mdx/src/mdx-client/code.tsx
@@ -32,10 +32,7 @@ export function InnerCode({
       
diff --git a/packages/mdx/src/mdx-plugin/plugin.ts b/packages/mdx/src/mdx-plugin/plugin.ts index e5550b3a..427e6b1e 100644 --- a/packages/mdx/src/mdx-plugin/plugin.ts +++ b/packages/mdx/src/mdx-plugin/plugin.ts @@ -15,6 +15,7 @@ type CodeHikeConfig = { theme: any lineNumbers?: boolean autoImport?: boolean + showCopyButton?: boolean } export function remarkCodeHike( diff --git a/packages/mdx/src/mini-editor/editor-tween.tsx b/packages/mdx/src/mini-editor/editor-tween.tsx index 8d128c1d..ced8dc5a 100644 --- a/packages/mdx/src/mini-editor/editor-tween.tsx +++ b/packages/mdx/src/mini-editor/editor-tween.tsx @@ -54,6 +54,8 @@ function EditorTween({ ...divProps }: EditorTweenProps) { const ref = React.createRef() + + const { showCopyButton, ...config } = codeConfig const { northPanel, southPanel, @@ -65,7 +67,7 @@ function EditorTween({ next || prev, t, backward, - codeConfig + config ) const [frozenHeight, freezeHeight] = React.useState< @@ -109,20 +111,20 @@ function EditorTween({ terminalPanel={terminalPanel} theme={codeConfig.theme} northButton={ - + showCopyButton ? ( + + ) : undefined } southButton={ - + showCopyButton ? ( + + ) : undefined } /> ) From d21f95cba462e9545b23fb545615cca1780879db Mon Sep 17 00:00:00 2001 From: Rodrigo Pombo Date: Thu, 5 May 2022 14:22:50 +0200 Subject: [PATCH 8/8] Add withClass annotation --- .../mdx/dev/content/comment-annotations.mdx | 18 +++ packages/mdx/pages/styles.css | 111 +----------------- packages/mdx/src/mdx-client/annotations.tsx | 20 ++++ 3 files changed, 40 insertions(+), 109 deletions(-) diff --git a/packages/mdx/dev/content/comment-annotations.mdx b/packages/mdx/dev/content/comment-annotations.mdx index 11f87ce0..05970d10 100644 --- a/packages/mdx/dev/content/comment-annotations.mdx +++ b/packages/mdx/dev/content/comment-annotations.mdx @@ -93,3 +93,21 @@ function lorem(ipsum, dolor = 1) { return $sit and consectetur(ipsum) or [] } ``` + +With class + +```js +function lorem(ipsum, dolor = 1) { + // withClass[15:19] annotation-class + const sit = ipsum == null && 0 + // withClass(1:2) annotation-class + dolor = sit - amet(dolor) + return sit ? consectetur(ipsum) : [] +} + +function adipiscing(...elit) { + console.log("hover me") + // withClass annotation-class + return elit.map(ipsum => ipsum.sit) +} +``` diff --git a/packages/mdx/pages/styles.css b/packages/mdx/pages/styles.css index 40188c83..e15a5db6 100644 --- a/packages/mdx/pages/styles.css +++ b/packages/mdx/pages/styles.css @@ -33,113 +33,6 @@ div#__next > div { color: black; } -/* -nav { - height: 40px; - overflow: hidden; +.annotation-class span { + text-decoration: line-through; } - -main { - flex: 1; - overflow: auto; -} */ - -/* main */ -/* -.columns { - display: flex; - min-height: 100%; -} - -.column { - margin-left: auto; - margin-right: auto; - flex: 1; - box-sizing: border-box; - padding: 0 6px 6px; - min-width: 400px; - max-width: 800px; -} - -.column > h2 { - padding: 6px; - margin: 0; - text-align: center; - font-size: 20px; - color: #ccc; -} - -.column > .content { - padding: 10px 18px; - background-color: #fff; - border-radius: 6px; -} - - -nav { - display: flex; - align-items: center; - background-color: #222; - color: #ccc; -} - -nav h1 { - margin: 0 16px 0 24px; -} -nav h1 a { - color: unset; - text-decoration: none; -} - -nav .version { - color: #aaa; - font-size: 14px; -} - -.radio { - text-align: center; - border: 1px solid #222; - border-radius: 4px; - overflow: hidden; - display: inline-block; - vertical-align: middle; - margin-left: 6px; -} -.radio button { - border: none; - background-color: #444; - color: #ccc; - height: 24px; -} -.radio button.selected { - background-color: #fafafa; - color: #222; -} - -nav label { - margin-right: 24px; -} */ - -/* nav select { - margin-left: 6px; - border-radius: 4px; - background-color: #fafafa; - height: 24px; -} */ - -/* result */ -/* -.result { - min-width: 900px; - width: 900px; - max-width: 900px; -} - -pre.shiki { - white-space: pre-wrap; -} - -.tailwind-font code { - font-family: ui-monospace, SFMono-Regular, Consolas, - "Liberation Mono", Menlo, monospace; -} */ diff --git a/packages/mdx/src/mdx-client/annotations.tsx b/packages/mdx/src/mdx-client/annotations.tsx index c6a50af3..69e589e6 100644 --- a/packages/mdx/src/mdx-client/annotations.tsx +++ b/packages/mdx/src/mdx-client/annotations.tsx @@ -15,6 +15,7 @@ export const annotationsMap: Record< label: Label, link: CodeLink, mark: Mark, + withClass: WithClass, } function Mark({ @@ -97,6 +98,25 @@ function Box({ ) } +function WithClass({ + children, + data, + style, + theme, +}: { + data: any + children: React.ReactNode + style?: React.CSSProperties + theme: any +}) { + const className = data as string + return ( + + {children} + + ) +} + function Background({ children, data,