From 819f419858ae14c69e3901d960fd52742a0141fd Mon Sep 17 00:00:00 2001 From: cyan33 Date: Wed, 30 May 2018 21:43:57 -0700 Subject: [PATCH 1/7] support multiple files for codesandbox import --- .../src/__tests__/__snapshots__/index.js.snap | 14 ++++---- .../gatsby-remark-code-repls/src/index.js | 33 ++++++++++++++----- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/packages/gatsby-remark-code-repls/src/__tests__/__snapshots__/index.js.snap b/packages/gatsby-remark-code-repls/src/__tests__/__snapshots__/index.js.snap index 949675345723f..be4299c3b7377 100644 --- a/packages/gatsby-remark-code-repls/src/__tests__/__snapshots__/index.js.snap +++ b/packages/gatsby-remark-code-repls/src/__tests__/__snapshots__/index.js.snap @@ -217,7 +217,7 @@ Object { "children": Array [ Object { "type": "html", - "value": "REPL", + "value": "REPL", }, ], "position": Position { @@ -259,7 +259,7 @@ Object { "children": Array [ Object { "type": "html", - "value": "REPL", + "value": "REPL", }, ], "position": Position { @@ -301,7 +301,7 @@ Object { "children": Array [ Object { "type": "html", - "value": "Click me", + "value": "Click me", }, ], "position": Position { @@ -343,7 +343,7 @@ Object { "children": Array [ Object { "type": "html", - "value": "Custom link text", + "value": "Custom link text", }, ], "position": Position { @@ -385,7 +385,7 @@ Object { "children": Array [ Object { "type": "html", - "value": "REPL", + "value": "REPL", }, ], "position": Position { @@ -427,7 +427,7 @@ Object { "children": Array [ Object { "type": "html", - "value": "REPL", + "value": "REPL", }, ], "position": Position { @@ -469,7 +469,7 @@ Object { "children": Array [ Object { "type": "html", - "value": "REPL", + "value": "REPL", }, ], "position": Position { diff --git a/packages/gatsby-remark-code-repls/src/index.js b/packages/gatsby-remark-code-repls/src/index.js index 8146c71117c13..b493e50c74cef 100644 --- a/packages/gatsby-remark-code-repls/src/index.js +++ b/packages/gatsby-remark-code-repls/src/index.js @@ -64,12 +64,27 @@ module.exports = ( return filePath } + const getMultipleFilesPaths = (urls, protocol, directory) => ( + urls.replace(protocol, ``).split(`,`).map((url) => { + if (!url.endsWith(`.js`) && !url.endsWith(`.css`)) { + url += `.js` + } + + return { + fileName: url.split(`/`).slice(-1)[0], // filename itself + filePath: normalizePath(join(directory, url)), // absolute path + } + }) + ) + const verifyFile = path => { if (!fs.existsSync(path)) { throw Error(`Invalid REPL link specified; no such file "${path}"`) } } + const verifyMultipleFiles = paths => paths.forEach((path) => verifyFile(path.filePath)) + map(markdownAST, (node, index, parent) => { if (node.type === `link`) { if (node.url.startsWith(PROTOCOL_BABEL)) { @@ -94,11 +109,8 @@ module.exports = ( convertNodeToLink(node, text, href, target) } else if (node.url.startsWith(PROTOCOL_CODE_SANDBOX)) { - const filePath = getFilePath(node.url, PROTOCOL_CODE_SANDBOX, directory) - - verifyFile(filePath) - - const code = fs.readFileSync(filePath, `utf8`) + const filesPaths = getMultipleFilesPaths(node.url, PROTOCOL_CODE_SANDBOX, directory) + verifyMultipleFiles(filesPaths) // CodeSandbox GET API requires a list of "files" keyed by name let parameters = { @@ -114,17 +126,22 @@ module.exports = ( } return map }, {}), + main: filesPaths[0].fileName, }, }, - "index.js": { - content: code, - }, "index.html": { content: html, }, }, } + filesPaths.forEach((path, i) => { + const code = fs.readFileSync(path.filePath, `utf8`) + parameters.files[path.fileName] = { + content: code, + } + }) + // This config JSON must then be lz-string compressed parameters = compress(JSON.stringify(parameters)) From 559654014e7341ea6d8d4aa8101595fe4c1fe85d Mon Sep 17 00:00:00 2001 From: cyan33 Date: Fri, 1 Jun 2018 15:00:47 -0700 Subject: [PATCH 2/7] add new test cases and refactor code --- .../src/__tests__/__snapshots__/index.js.snap | 48 +++++++++++++++++-- .../src/__tests__/index.js | 24 ++++++++++ .../gatsby-remark-code-repls/src/index.js | 23 +++++---- 3 files changed, 82 insertions(+), 13 deletions(-) diff --git a/packages/gatsby-remark-code-repls/src/__tests__/__snapshots__/index.js.snap b/packages/gatsby-remark-code-repls/src/__tests__/__snapshots__/index.js.snap index be4299c3b7377..72b8c8d83a7cc 100644 --- a/packages/gatsby-remark-code-repls/src/__tests__/__snapshots__/index.js.snap +++ b/packages/gatsby-remark-code-repls/src/__tests__/__snapshots__/index.js.snap @@ -217,7 +217,7 @@ Object { "children": Array [ Object { "type": "html", - "value": "REPL", + "value": "REPL", }, ], "position": Position { @@ -427,7 +427,7 @@ Object { "children": Array [ Object { "type": "html", - "value": "REPL", + "value": "REPL", }, ], "position": Position { @@ -469,7 +469,7 @@ Object { "children": Array [ Object { "type": "html", - "value": "REPL", + "value": "REPL", }, ], "position": Position { @@ -504,6 +504,48 @@ Object { } `; +exports[`gatsby-remark-code-repls CodeSandbox remark transform supports importing multiple files 1`] = ` +Object { + "children": Array [ + Object { + "children": Array [ + Object { + "type": "html", + "value": "REPL", + }, + ], + "position": Position { + "end": Object { + "column": 95, + "line": 1, + "offset": 94, + }, + "indent": Array [], + "start": Object { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "paragraph", + }, + ], + "position": Object { + "end": Object { + "column": 95, + "line": 1, + "offset": 94, + }, + "start": Object { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "root", +} +`; + exports[`gatsby-remark-code-repls Codepen remark transform generates a link for files in nested directories 1`] = ` Object { "children": Array [ diff --git a/packages/gatsby-remark-code-repls/src/__tests__/index.js b/packages/gatsby-remark-code-repls/src/__tests__/index.js index 51ecd876d2d67..79ce1a482d22d 100644 --- a/packages/gatsby-remark-code-repls/src/__tests__/index.js +++ b/packages/gatsby-remark-code-repls/src/__tests__/index.js @@ -121,6 +121,22 @@ describe(`gatsby-remark-code-repls`, () => { ) }) + it(`errors if you provide multiple files in non-codesandbox examples`, () => { + const markdownAST = remark.parse( + `[](${protocol}path/to/nested/file.js,path/to/nested/anotherFile.js,path/to/nested/file.css)` + ) + const runPlugin = () => plugin({ markdownAST }, { directory: `examples` }) + + if (protocol !== PROTOCOL_CODE_SANDBOX) { + expect(runPlugin).toThrow( + `Code example path should only contain a single file, but found more than one: ` + + `path/to/nested/file.js,path/to/nested/anotherFile.js,path/to/nested/file.css` + ) + } else { + expect(runPlugin).not.toThrow() + } + }) + if (protocol === PROTOCOL_CODE_SANDBOX) { it(`supports custom html config option for index html`, () => { const markdownAST = remark.parse( @@ -153,6 +169,14 @@ describe(`gatsby-remark-code-repls`, () => { expect(transformed).toMatchSnapshot() }) + + it(`supports importing multiple files`, () => { + const markdownAST = remark.parse( + `[](${protocol}path/to/nested/file.js,path/to/nested/anotherFile.js,path/to/nested/file.css)` + ) + const transformed = plugin({ markdownAST }, { directory: `examples` }) + expect(transformed).toMatchSnapshot() + }) } }) }) diff --git a/packages/gatsby-remark-code-repls/src/index.js b/packages/gatsby-remark-code-repls/src/index.js index b493e50c74cef..5e2fc7b89d7d6 100644 --- a/packages/gatsby-remark-code-repls/src/index.js +++ b/packages/gatsby-remark-code-repls/src/index.js @@ -57,7 +57,7 @@ module.exports = ( const getFilePath = (url, protocol, directory) => { let filePath = url.replace(protocol, ``) - if (!filePath.endsWith(`.js`)) { + if (!filePath.endsWith(`.js`) && !filePath.endsWith(`.css`)) { filePath += `.js` } filePath = normalizePath(join(directory, filePath)) @@ -71,26 +71,29 @@ module.exports = ( } return { - fileName: url.split(`/`).slice(-1)[0], // filename itself + url, // filename itself filePath: normalizePath(join(directory, url)), // absolute path } }) ) - const verifyFile = path => { + const verifyFile = (path, protocol) => { + if (protocol !== PROTOCOL_CODE_SANDBOX && path.split(`,`).length > 1) { + throw Error(`Code example path should only contain a single file, but found more than one: ${path.replace(directory, ``)}`) + } if (!fs.existsSync(path)) { throw Error(`Invalid REPL link specified; no such file "${path}"`) } } - const verifyMultipleFiles = paths => paths.forEach((path) => verifyFile(path.filePath)) + const verifyMultipleFiles = (paths, protocol) => paths.forEach((path) => verifyFile(path.filePath, protocol)) map(markdownAST, (node, index, parent) => { if (node.type === `link`) { if (node.url.startsWith(PROTOCOL_BABEL)) { const filePath = getFilePath(node.url, PROTOCOL_BABEL, directory) - verifyFile(filePath) + verifyFile(filePath, PROTOCOL_BABEL) const code = compress(fs.readFileSync(filePath, `utf8`)) const href = `https://babeljs.io/repl/#?presets=react&code_lz=${code}` @@ -101,7 +104,7 @@ module.exports = ( } else if (node.url.startsWith(PROTOCOL_CODEPEN)) { const filePath = getFilePath(node.url, PROTOCOL_CODEPEN, directory) - verifyFile(filePath) + verifyFile(filePath, PROTOCOL_CODEPEN) const href = node.url.replace(PROTOCOL_CODEPEN, `/redirect-to-codepen/`) const text = @@ -110,7 +113,7 @@ module.exports = ( convertNodeToLink(node, text, href, target) } else if (node.url.startsWith(PROTOCOL_CODE_SANDBOX)) { const filesPaths = getMultipleFilesPaths(node.url, PROTOCOL_CODE_SANDBOX, directory) - verifyMultipleFiles(filesPaths) + verifyMultipleFiles(filesPaths, PROTOCOL_CODE_SANDBOX) // CodeSandbox GET API requires a list of "files" keyed by name let parameters = { @@ -126,7 +129,7 @@ module.exports = ( } return map }, {}), - main: filesPaths[0].fileName, + main: filesPaths[0].url, }, }, "index.html": { @@ -137,7 +140,7 @@ module.exports = ( filesPaths.forEach((path, i) => { const code = fs.readFileSync(path.filePath, `utf8`) - parameters.files[path.fileName] = { + parameters.files[path.url] = { content: code, } }) @@ -153,7 +156,7 @@ module.exports = ( } else if (node.url.startsWith(PROTOCOL_RAMDA)) { const filePath = getFilePath(node.url, PROTOCOL_RAMDA, directory) - verifyFile(filePath) + verifyFile(filePath, PROTOCOL_RAMDA) // Don't use `compress()` as the Ramda REPL won't understand the output. // It uses URI to encode the code for its urls, so we do the same. From 7197cd8985c015693397c8990730a6fa9f42b0db Mon Sep 17 00:00:00 2001 From: cyan33 Date: Fri, 20 Jul 2018 13:31:54 -0700 Subject: [PATCH 3/7] fix the nits --- packages/gatsby-remark-code-repls/src/__tests__/index.js | 5 +++-- packages/gatsby-remark-code-repls/src/index.js | 9 ++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/gatsby-remark-code-repls/src/__tests__/index.js b/packages/gatsby-remark-code-repls/src/__tests__/index.js index 79ce1a482d22d..153906657ec8a 100644 --- a/packages/gatsby-remark-code-repls/src/__tests__/index.js +++ b/packages/gatsby-remark-code-repls/src/__tests__/index.js @@ -129,8 +129,9 @@ describe(`gatsby-remark-code-repls`, () => { if (protocol !== PROTOCOL_CODE_SANDBOX) { expect(runPlugin).toThrow( - `Code example path should only contain a single file, but found more than one: ` + - `path/to/nested/file.js,path/to/nested/anotherFile.js,path/to/nested/file.css` + `Code example path should only contain a single file, but found more than one: ` + + `path/to/nested/file.js,path/to/nested/anotherFile.js,path/to/nested/file.css. ` + + `Only CodeSandbox REPL supports multiple files entries, the protocol prefix of which starts with codesandbox://` ) } else { expect(runPlugin).not.toThrow() diff --git a/packages/gatsby-remark-code-repls/src/index.js b/packages/gatsby-remark-code-repls/src/index.js index 5e2fc7b89d7d6..b744662c01240 100644 --- a/packages/gatsby-remark-code-repls/src/index.js +++ b/packages/gatsby-remark-code-repls/src/index.js @@ -57,7 +57,7 @@ module.exports = ( const getFilePath = (url, protocol, directory) => { let filePath = url.replace(protocol, ``) - if (!filePath.endsWith(`.js`) && !filePath.endsWith(`.css`)) { + if (!filePath.indexOf(`.`) > 0) { filePath += `.js` } filePath = normalizePath(join(directory, filePath)) @@ -66,7 +66,7 @@ module.exports = ( const getMultipleFilesPaths = (urls, protocol, directory) => ( urls.replace(protocol, ``).split(`,`).map((url) => { - if (!url.endsWith(`.js`) && !url.endsWith(`.css`)) { + if (!url.indexOf(`.`) > 0) { url += `.js` } @@ -79,7 +79,10 @@ module.exports = ( const verifyFile = (path, protocol) => { if (protocol !== PROTOCOL_CODE_SANDBOX && path.split(`,`).length > 1) { - throw Error(`Code example path should only contain a single file, but found more than one: ${path.replace(directory, ``)}`) + throw Error( + `Code example path should only contain a single file, but found more than one: ${path.replace(directory, ``)}. ` + + `Only CodeSandbox REPL supports multiple files entries, the protocol prefix of which starts with ${PROTOCOL_CODE_SANDBOX}` + ) } if (!fs.existsSync(path)) { throw Error(`Invalid REPL link specified; no such file "${path}"`) From 87be5f16a7fe14954e8807e2c6c10cbac62c18ba Mon Sep 17 00:00:00 2001 From: cyan33 Date: Sun, 22 Jul 2018 14:53:48 -0700 Subject: [PATCH 4/7] update document about supporting multiple files --- packages/gatsby-remark-code-repls/README.md | 35 +++++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/packages/gatsby-remark-code-repls/README.md b/packages/gatsby-remark-code-repls/README.md index dc3e177eb9305..4459779b66570 100644 --- a/packages/gatsby-remark-code-repls/README.md +++ b/packages/gatsby-remark-code-repls/README.md @@ -42,7 +42,7 @@ to HTML links that open the embedded code examples in a REPL. For example: ```html -[See it in Babel](babel://hello-world) +[See it in Babel](babel://hello-world.js) @@ -50,7 +50,7 @@ to HTML links that open the embedded code examples in a REPL. For example: -[Try it on CodePen](codepen://components-and-props/rendering-a-component) +[Try it on CodePen](codepen://components-and-props/rendering-a-component.js) @@ -58,7 +58,7 @@ to HTML links that open the embedded code examples in a REPL. For example: -[Try it on CodeSandbox](codesandbox://components-and-props/rendering-a-component) +[Try it on CodeSandbox](codesandbox://components-and-props/rendering-a-component.js) @@ -66,6 +66,35 @@ to HTML links that open the embedded code examples in a REPL. For example: ``` +### Creating CodeSandbox Example With Multiple Files + +Sometimes a larger code example would require more than a single file, with various types. For example, you might have an example folder like this: + +``` +├── my-example +│   ├── index.js +│   ├── util.js +│   └── index.css +``` + +CodesandBox supports code example with multiple files. With this plugin, you can do: + +```html +[Try it on CodePen](codesandbox://my-example/index.js,my-example/util.js,my-example/index.css) +``` + +> Caveat +> +> The first file path you passed to `codesandbox://` will be the entry of your example, that is, the `main` field specified in your `package.json`. + +And in `index.js`, you could import other files using the ES6 modules syntax: + +```js +import { foo } from './utils'; + +import './index.css'; +``` + ### How does it work? Codepen links point to Gatsby pages (also created by this plug-in) that redirect From 96b044970bb85ce51c05da644b6daaeeb285b7a4 Mon Sep 17 00:00:00 2001 From: cyan33 Date: Sun, 22 Jul 2018 15:10:19 -0700 Subject: [PATCH 5/7] replace indexOf with includes --- packages/gatsby-remark-code-repls/src/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/gatsby-remark-code-repls/src/index.js b/packages/gatsby-remark-code-repls/src/index.js index b744662c01240..069c679774fd6 100644 --- a/packages/gatsby-remark-code-repls/src/index.js +++ b/packages/gatsby-remark-code-repls/src/index.js @@ -57,7 +57,7 @@ module.exports = ( const getFilePath = (url, protocol, directory) => { let filePath = url.replace(protocol, ``) - if (!filePath.indexOf(`.`) > 0) { + if (!filePath.includes(`.`)) { filePath += `.js` } filePath = normalizePath(join(directory, filePath)) @@ -66,7 +66,7 @@ module.exports = ( const getMultipleFilesPaths = (urls, protocol, directory) => ( urls.replace(protocol, ``).split(`,`).map((url) => { - if (!url.indexOf(`.`) > 0) { + if (!url.includes(`.`)) { url += `.js` } From 62702c2ab28b01e28cdf963f17bd4955bc9b2824 Mon Sep 17 00:00:00 2001 From: cyan33 Date: Sun, 22 Jul 2018 15:16:57 -0700 Subject: [PATCH 6/7] ran prettier --- packages/gatsby-remark-code-repls/README.md | 6 +-- .../src/__tests__/index.js | 5 ++- .../gatsby-remark-code-repls/src/index.js | 40 ++++++++++++------- 3 files changed, 31 insertions(+), 20 deletions(-) diff --git a/packages/gatsby-remark-code-repls/README.md b/packages/gatsby-remark-code-repls/README.md index 4459779b66570..0df6248ac6caf 100644 --- a/packages/gatsby-remark-code-repls/README.md +++ b/packages/gatsby-remark-code-repls/README.md @@ -80,7 +80,7 @@ Sometimes a larger code example would require more than a single file, with vari CodesandBox supports code example with multiple files. With this plugin, you can do: ```html -[Try it on CodePen](codesandbox://my-example/index.js,my-example/util.js,my-example/index.css) +[Try it on CodeSandbox](codesandbox://my-example/index.js,my-example/util.js,my-example/index.css) ``` > Caveat @@ -90,9 +90,9 @@ CodesandBox supports code example with multiple files. With this plugin, you can And in `index.js`, you could import other files using the ES6 modules syntax: ```js -import { foo } from './utils'; +import { foo } from "./utils" -import './index.css'; +import "./index.css" ``` ### How does it work? diff --git a/packages/gatsby-remark-code-repls/src/__tests__/index.js b/packages/gatsby-remark-code-repls/src/__tests__/index.js index 153906657ec8a..48f6e5dc6be77 100644 --- a/packages/gatsby-remark-code-repls/src/__tests__/index.js +++ b/packages/gatsby-remark-code-repls/src/__tests__/index.js @@ -125,11 +125,12 @@ describe(`gatsby-remark-code-repls`, () => { const markdownAST = remark.parse( `[](${protocol}path/to/nested/file.js,path/to/nested/anotherFile.js,path/to/nested/file.css)` ) - const runPlugin = () => plugin({ markdownAST }, { directory: `examples` }) + const runPlugin = () => + plugin({ markdownAST }, { directory: `examples` }) if (protocol !== PROTOCOL_CODE_SANDBOX) { expect(runPlugin).toThrow( - `Code example path should only contain a single file, but found more than one: ` + + `Code example path should only contain a single file, but found more than one: ` + `path/to/nested/file.js,path/to/nested/anotherFile.js,path/to/nested/file.css. ` + `Only CodeSandbox REPL supports multiple files entries, the protocol prefix of which starts with codesandbox://` ) diff --git a/packages/gatsby-remark-code-repls/src/index.js b/packages/gatsby-remark-code-repls/src/index.js index 069c679774fd6..60a1bf9f397a8 100644 --- a/packages/gatsby-remark-code-repls/src/index.js +++ b/packages/gatsby-remark-code-repls/src/index.js @@ -64,23 +64,28 @@ module.exports = ( return filePath } - const getMultipleFilesPaths = (urls, protocol, directory) => ( - urls.replace(protocol, ``).split(`,`).map((url) => { - if (!url.includes(`.`)) { - url += `.js` - } - - return { - url, // filename itself - filePath: normalizePath(join(directory, url)), // absolute path - } - }) - ) + const getMultipleFilesPaths = (urls, protocol, directory) => + urls + .replace(protocol, ``) + .split(`,`) + .map(url => { + if (!url.includes(`.`)) { + url += `.js` + } + + return { + url, // filename itself + filePath: normalizePath(join(directory, url)), // absolute path + } + }) const verifyFile = (path, protocol) => { if (protocol !== PROTOCOL_CODE_SANDBOX && path.split(`,`).length > 1) { throw Error( - `Code example path should only contain a single file, but found more than one: ${path.replace(directory, ``)}. ` + + `Code example path should only contain a single file, but found more than one: ${path.replace( + directory, + `` + )}. ` + `Only CodeSandbox REPL supports multiple files entries, the protocol prefix of which starts with ${PROTOCOL_CODE_SANDBOX}` ) } @@ -89,7 +94,8 @@ module.exports = ( } } - const verifyMultipleFiles = (paths, protocol) => paths.forEach((path) => verifyFile(path.filePath, protocol)) + const verifyMultipleFiles = (paths, protocol) => + paths.forEach(path => verifyFile(path.filePath, protocol)) map(markdownAST, (node, index, parent) => { if (node.type === `link`) { @@ -115,7 +121,11 @@ module.exports = ( convertNodeToLink(node, text, href, target) } else if (node.url.startsWith(PROTOCOL_CODE_SANDBOX)) { - const filesPaths = getMultipleFilesPaths(node.url, PROTOCOL_CODE_SANDBOX, directory) + const filesPaths = getMultipleFilesPaths( + node.url, + PROTOCOL_CODE_SANDBOX, + directory + ) verifyMultipleFiles(filesPaths, PROTOCOL_CODE_SANDBOX) // CodeSandbox GET API requires a list of "files" keyed by name From 4d1a232e582ae4f143b144d8972027d23f5b97b0 Mon Sep 17 00:00:00 2001 From: cyan33 Date: Mon, 23 Jul 2018 09:30:50 -0700 Subject: [PATCH 7/7] CodesandBox -> CodeSandbox --- packages/gatsby-remark-code-repls/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/gatsby-remark-code-repls/README.md b/packages/gatsby-remark-code-repls/README.md index 0df6248ac6caf..e7f06ca3094c3 100644 --- a/packages/gatsby-remark-code-repls/README.md +++ b/packages/gatsby-remark-code-repls/README.md @@ -77,7 +77,7 @@ Sometimes a larger code example would require more than a single file, with vari │   └── index.css ``` -CodesandBox supports code example with multiple files. With this plugin, you can do: +CodeSandbox supports code example with multiple files. With this plugin, you can do: ```html [Try it on CodeSandbox](codesandbox://my-example/index.js,my-example/util.js,my-example/index.css)