diff --git a/content/tutorial/tutorial.md b/content/tutorial/tutorial.md
index 4fcf1a937..9ca297200 100644
--- a/content/tutorial/tutorial.md
+++ b/content/tutorial/tutorial.md
@@ -129,7 +129,7 @@ return React.createElement('div', {className: 'shopping-list'},
);
```
-[See full expanded version.](https://babeljs.io/repl/#?babili=false&evaluate=false&lineWrap=false&presets=react&targets=&browsers=&builtIns=false&debug=false&experimental=false&loose=false&spec=false&playground=true&code=%3Cdiv%20className%3D%22shopping-list%22%3E%0A%20%20%3Ch1%3EShopping%20List%20for%20%7Bprops.name%7D%3C%2Fh1%3E%0A%20%20%3Cul%3E%0A%20%20%20%20%3Cli%3EInstagram%3C%2Fli%3E%0A%20%20%20%20%3Cli%3EWhatsApp%3C%2Fli%3E%0A%20%20%20%20%3Cli%3EOculus%3C%2Fli%3E%0A%20%20%3C%2Ful%3E%0A%3C%2Fdiv%3E)
+[See full expanded version.](babel-repl://tutorial-expanded-version)
If you're curious, `createElement()` is described in more detail in the [API reference](/docs/react-api.html#createelement), but we won't be using it directly in this tutorial. Instead, we will keep using JSX.
diff --git a/examples/tutorial-expanded-version.js b/examples/tutorial-expanded-version.js
new file mode 100644
index 000000000..767a233fb
--- /dev/null
+++ b/examples/tutorial-expanded-version.js
@@ -0,0 +1,8 @@
+
+
Shopping List for {props.name}
+
+ - Instagram
+ - WhatsApp
+ - Oculus
+
+
\ No newline at end of file
diff --git a/gatsby-config.js b/gatsby-config.js
index a645f86a5..35a5bf445 100644
--- a/gatsby-config.js
+++ b/gatsby-config.js
@@ -62,6 +62,12 @@ module.exports = {
directory: 'examples',
},
},
+ {
+ resolve: 'gatsby-remark-babel-repl-link',
+ options: {
+ directory: 'examples',
+ },
+ },
'gatsby-remark-use-jsx',
{
resolve: 'gatsby-remark-prismjs',
diff --git a/package.json b/package.json
index 8501d1def..e888cb43f 100644
--- a/package.json
+++ b/package.json
@@ -85,6 +85,7 @@
},
"devDependencies": {
"eslint-config-prettier": "^2.6.0",
+ "lz-string": "^1.4.4",
"recursive-readdir": "^2.2.1",
"unist-util-map": "^1.0.3"
}
diff --git a/plugins/gatsby-remark-babel-repl-link/index.js b/plugins/gatsby-remark-babel-repl-link/index.js
new file mode 100644
index 000000000..e3f13e20c
--- /dev/null
+++ b/plugins/gatsby-remark-babel-repl-link/index.js
@@ -0,0 +1,68 @@
+const {existsSync, readFileSync} = require('fs');
+const LZString = require('lz-string');
+const {join} = require('path');
+const map = require('unist-util-map');
+
+const PROTOCOL = 'babel-repl://';
+
+// Matches compression used in Babel REPL
+// https://github.com/babel/website/blob/master/js/repl/UriUtils.js
+const compress = string =>
+ LZString.compressToBase64(string)
+ .replace(/\+/g, '-') // Convert '+' to '-'
+ .replace(/\//g, '_') // Convert '/' to '_'
+ .replace(/=+$/, ''); // Remove ending '='
+
+module.exports = ({markdownAST}, {directory}) => {
+ map(markdownAST, (node, index, parent) => {
+ if (!directory.endsWith('/')) {
+ directory += '/';
+ }
+
+ if (node.type === 'link' && node.url.startsWith(PROTOCOL)) {
+ let filePath = node.url.replace(PROTOCOL, directory);
+ if (!filePath.endsWith('.js')) {
+ filePath += '.js';
+ }
+ filePath = join(__dirname, '../..', filePath);
+
+ // Verify that the specified example file exists.
+ if (!existsSync(filePath)) {
+ console.error(
+ `Invalid Babel REPL link specified; no such file "${filePath}"`,
+ );
+ process.exit(1);
+ }
+
+ const code = compress(readFileSync(filePath, 'utf8'));
+ const href = `https://babeljs.io/repl/#?presets=react&code_lz=${code}`;
+ const text = node.children[0].value;
+
+ const anchorOpenNode = {
+ type: 'html',
+ value: ``,
+ };
+
+ const textNode = {
+ type: 'text',
+ value: text,
+ };
+
+ const anchorCloseNode = {
+ type: 'html',
+ value: '',
+ };
+
+ parent.children.splice(
+ index,
+ 1,
+ anchorOpenNode,
+ textNode,
+ anchorCloseNode,
+ );
+ }
+
+ // No change
+ return node;
+ });
+};
diff --git a/plugins/gatsby-remark-babel-repl-link/package.json b/plugins/gatsby-remark-babel-repl-link/package.json
new file mode 100644
index 000000000..a0318cc57
--- /dev/null
+++ b/plugins/gatsby-remark-babel-repl-link/package.json
@@ -0,0 +1,4 @@
+{
+ "name": "gatsby-remark-babel-repl-link",
+ "version": "0.0.1"
+}
\ No newline at end of file
diff --git a/plugins/gatsby-remark-codepen-examples/index.js b/plugins/gatsby-remark-codepen-examples/index.js
index f1da51e4f..7e4ff3327 100644
--- a/plugins/gatsby-remark-codepen-examples/index.js
+++ b/plugins/gatsby-remark-codepen-examples/index.js
@@ -5,7 +5,6 @@ const map = require('unist-util-map');
const CODEPEN_PROTOCOL = 'codepen://';
const DEFAULT_LINK_TEXT = 'Try it on CodePen';
-// TODO target="_blank"
module.exports = ({markdownAST}, {directory}) => {
map(markdownAST, (node, index, parent) => {
if (!directory.startsWith('/')) {
@@ -22,7 +21,7 @@ module.exports = ({markdownAST}, {directory}) => {
// from: [Try the Hello World example on CodePen](codepen:hello-world)
// to: Try the Hello World example on CodePen
if (node.type === 'link' && node.url.startsWith(CODEPEN_PROTOCOL)) {
- const href = node.url.replace(CODEPEN_PROTOCOL, `${directory}`);
+ const href = node.url.replace(CODEPEN_PROTOCOL, directory);
const text =
node.children.length === 0 ? DEFAULT_LINK_TEXT : node.children[0].value;
diff --git a/yarn.lock b/yarn.lock
index 9640d346a..abe90f6bf 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6086,6 +6086,10 @@ ltcdr@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/ltcdr/-/ltcdr-2.2.1.tgz#5ab87ad1d4c1dab8e8c08bbf037ee0c1902287cf"
+lz-string@^1.4.4:
+ version "1.4.4"
+ resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26"
+
macaddress@^0.2.8:
version "0.2.8"
resolved "https://registry.yarnpkg.com/macaddress/-/macaddress-0.2.8.tgz#5904dc537c39ec6dbefeae902327135fa8511f12"