Skip to content

Commit 25c68e5

Browse files
author
Guy Thomas
committed
dont merge. Just for installing as a dep
1 parent d8abcb9 commit 25c68e5

File tree

2 files changed

+183
-1
lines changed

2 files changed

+183
-1
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,3 @@ node_modules
44

55
yarn-error.log
66

7-
/index.js

index.js

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
'use strict';
2+
3+
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
4+
5+
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
6+
7+
var fs = require('fs');
8+
var path = require('path');
9+
var LZString = require('lz-string');
10+
var normalizePath = require('normalize-path');
11+
var map = require('unist-util-map');
12+
var queryString = require('query-string');
13+
14+
var DEFAULT_PROTOCOL = 'embedded-codesandbox://';
15+
var DEFAULT_EMBED_OPTIONS = {
16+
view: 'preview',
17+
hidenavigation: 1
18+
};
19+
var DEFAULT_GET_IFRAME = function DEFAULT_GET_IFRAME(url) {
20+
return '<iframe src="' + url + '" class="embedded-codesandbox" sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"></iframe>';
21+
};
22+
23+
// Matches compression used in Babel and CodeSandbox REPLs
24+
// https://github.com/babel/website/blob/master/js/repl/UriUtils.js
25+
var compress = function compress(string) {
26+
return LZString.compressToBase64(string).replace(/\+/g, '-') // Convert '+' to '-'
27+
.replace(/\//g, '_') // Convert '/' to '_'
28+
.replace(/=+$/, '');
29+
}; // Remove ending '='
30+
31+
var ignoredFiles = new Set(['node_modules', 'package-lock.json', 'yarn.lock']);
32+
33+
var getAllFiles = function getAllFiles(dirPath) {
34+
return fs.readdirSync(dirPath).reduce(function (acc, file) {
35+
if (ignoredFiles.has(file)) return acc;
36+
var relativePath = dirPath + '/' + file;
37+
var isDirectory = fs.statSync(relativePath).isDirectory();
38+
var additions = isDirectory ? getAllFiles(relativePath) : [relativePath];
39+
return [].concat(_toConsumableArray(acc), _toConsumableArray(additions));
40+
}, []);
41+
};
42+
43+
module.exports = function (_ref, _ref2) {
44+
var markdownAST = _ref.markdownAST;
45+
var rootDirectory = _ref2.directory,
46+
_ref2$protocol = _ref2.protocol,
47+
protocol = _ref2$protocol === undefined ? DEFAULT_PROTOCOL : _ref2$protocol,
48+
_ref2$embedOptions = _ref2.embedOptions,
49+
embedOptions = _ref2$embedOptions === undefined ? DEFAULT_EMBED_OPTIONS : _ref2$embedOptions,
50+
_ref2$getIframe = _ref2.getIframe,
51+
getIframe = _ref2$getIframe === undefined ? DEFAULT_GET_IFRAME : _ref2$getIframe;
52+
53+
if (!rootDirectory) {
54+
throw Error('Required option "directory" not specified');
55+
} else if (!fs.existsSync(rootDirectory)) {
56+
throw Error('Cannot find directory "' + rootDirectory + '"');
57+
} else if (!rootDirectory.endsWith('/')) {
58+
rootDirectory += '/';
59+
}
60+
61+
var getDirectoryPath = function getDirectoryPath(url) {
62+
var directoryPath = url.replace(protocol, '');
63+
var fullPath = path.join(rootDirectory, directoryPath);
64+
return normalizePath(fullPath);
65+
};
66+
67+
var getFilesList = function getFilesList(directory) {
68+
var packageJsonFound = false;
69+
var folderFiles = getAllFiles(directory);
70+
var basePathRE = new RegExp('^' + directory + '/');
71+
var sandboxFiles = folderFiles.map(function (file) {
72+
return file.replace(basePathRE, '');
73+
})
74+
// we ignore the package.json file as it will
75+
// be handled separately
76+
.filter(function (file) {
77+
return !file.includes('package.json');
78+
}).map(function (relativePath) {
79+
var fullFilePath = path.resolve(__dirname, directory, relativePath);
80+
var content = fs.readFileSync(fullFilePath, 'utf-8');
81+
return {
82+
name: relativePath,
83+
content: content
84+
};
85+
});
86+
87+
var workingDir = directory;
88+
while (!packageJsonFound) {
89+
// first read all files in the folder and look
90+
// for a package.json there
91+
var files = fs.readdirSync(workingDir);
92+
var packageJson = getPackageJsonFile(files);
93+
if (packageJson) {
94+
var fullFilePath = path.resolve(workingDir, 'package.json');
95+
var content = fs.readFileSync(fullFilePath, 'utf-8');
96+
sandboxFiles.push({
97+
name: 'package.json',
98+
content: content
99+
});
100+
packageJsonFound = true;
101+
// if root folder is reached, use a fallback default
102+
// value as content, to ensure the sandbox is always working
103+
} else if (path.resolve(workingDir) === path.resolve(rootDirectory)) {
104+
sandboxFiles.push({
105+
name: 'package.json',
106+
content: '{ "name": "example" }'
107+
});
108+
packageJsonFound = true;
109+
// if not present, work up the folders
110+
} else {
111+
workingDir = path.join(workingDir, '..');
112+
}
113+
}
114+
115+
return sandboxFiles;
116+
};
117+
118+
var getPackageJsonFile = function getPackageJsonFile(fileList) {
119+
return fileList.find(function (file) {
120+
return file.includes('package.json');
121+
});
122+
};
123+
124+
var createParams = function createParams(files) {
125+
var filesObj = files.reduce(function (prev, current) {
126+
// parse package.json first
127+
if (current.name.includes('package.json')) {
128+
prev[current.name] = { content: JSON.parse(current.content) };
129+
} else {
130+
prev[current.name] = { content: current.content };
131+
}
132+
return prev;
133+
}, {});
134+
var params = {
135+
files: filesObj
136+
};
137+
return compress(JSON.stringify(params));
138+
};
139+
140+
var getUrlParts = function getUrlParts(url) {
141+
var splitUrl = url.split('?');
142+
return {
143+
base: splitUrl[0],
144+
query: queryString.parse(splitUrl[1])
145+
};
146+
};
147+
148+
var convertNodeToEmbedded = function convertNodeToEmbedded(node, params) {
149+
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
150+
151+
delete node.children;
152+
delete node.position;
153+
delete node.title;
154+
delete node.url;
155+
156+
// merge the overriding options with the plugin one
157+
var mergedOptions = _extends({}, embedOptions, options);
158+
var encodedEmbedOptions = encodeURIComponent(queryString.stringify(mergedOptions));
159+
var sandboxUrl = 'https://codesandbox.io/api/v1/sandboxes/define?embed=1&parameters=' + params + '&query=' + encodedEmbedOptions;
160+
var embedded = getIframe(sandboxUrl);
161+
162+
node.type = 'html';
163+
node.value = embedded;
164+
};
165+
166+
map(markdownAST, function (node, index, parent) {
167+
if (node.type === 'link' && node.url.startsWith(protocol)) {
168+
// split the url in base and query to allow user
169+
// to customise embedding options on a per-node basis
170+
var url = getUrlParts(node.url);
171+
// get all files in the folder and generate
172+
// the embeddeing parameters
173+
var dir = getDirectoryPath(url.base);
174+
var files = getFilesList(dir);
175+
var params = createParams(files);
176+
convertNodeToEmbedded(node, params, url.query);
177+
}
178+
179+
return node;
180+
});
181+
182+
return markdownAST;
183+
};

0 commit comments

Comments
 (0)