Skip to content

Commit 85cee41

Browse files
crutchcornMichaelDeBoey
authored andcommitted
feat: added initial StackBlitz support
1 parent 668d719 commit 85cee41

File tree

4 files changed

+97
-0
lines changed

4 files changed

+97
-0
lines changed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import cases from 'jest-in-case';
2+
3+
import plugin from '../../';
4+
import { getHTML, shouldTransform } from '../../transformers/StackBlitz';
5+
6+
import { cache, getMarkdownASTForFile, mdastToHtml } from '../helpers';
7+
8+
cases(
9+
'url validation',
10+
({ url, valid }) => {
11+
expect(shouldTransform(url)).toBe(valid);
12+
},
13+
{
14+
'non-StackBlitz url': {
15+
url: 'https://not-a-stackblitz-url.com',
16+
valid: false,
17+
},
18+
"non-StackBlitz url ending with 'stackblitz.com'": {
19+
url: 'https://this-is-not-stackblitz.com',
20+
valid: false,
21+
},
22+
"non-CodeSandbox url ending with 'stackblitz.com' having '/edit/'": {
23+
url: 'https://this-is-not-stackblitz.com/edit/start-to-source-1-ng-template',
24+
valid: false,
25+
},
26+
'embed url': {
27+
url: 'https://stackblitz.com/edit/start-to-source-1-ng-template',
28+
valid: true,
29+
},
30+
'embed url with parameters': {
31+
url: 'https://stackblitz.com/edit/start-to-source-1-ng-template?file=src/app/app.component.ts',
32+
valid: true,
33+
},
34+
}
35+
);
36+
37+
test('Gets the correct StackBlitz iframe', () => {
38+
const html = getHTML('https://stackblitz.com/edit/start-to-source-1-ng-template');
39+
40+
expect(html).toMatchInlineSnapshot(
41+
`<iframe src="https://stackblitz.com/edit/start-to-source-1-ng-template?embed=1" style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;" sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"></iframe>`
42+
);
43+
});
44+
45+
test('Plugin can transform StackBlitz links', async () => {
46+
const markdownAST = getMarkdownASTForFile('StackBlitz');
47+
48+
const processedAST = await plugin({ cache, markdownAST });
49+
50+
expect(mdastToHtml(processedAST)).toMatchInlineSnapshot(`
51+
<p>https://not-a-stackblitz-url.com</p>
52+
<p>https://this-is-not-stackblitz.com</p>
53+
<p>https://this-is-not-stackblitz.com/edit/start-to-source-1-ng-template</p>
54+
<iframe src="https://stackblitz.com/edit/start-to-source-1-ng-template?embed=1" style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;" sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"></iframe>
55+
<iframe src="https://stackblitz.com/edit/start-to-source-1-ng-template?embed=1&file=src/app/app.component.ts" style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;" sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"></iframe>
56+
57+
`);
58+
});
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
https://not-a-stackblitz-url.com
2+
3+
https://this-is-not-stackblitz.com
4+
5+
https://this-is-not-stackblitz.com/edit/start-to-source-1-ng-template
6+
7+
https://stackblitz.com/edit/start-to-source-1-ng-template
8+
9+
https://stackblitz.com/edit/start-to-source-1-ng-template?file=src/app/app.component.ts

src/transformers/StackBlitz.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
export const shouldTransform = (url) => {
2+
const { host, pathname } = new URL(url);
3+
4+
return (
5+
['stackblitz.com'].includes(host) &&
6+
pathname.includes('/edit/')
7+
);
8+
};
9+
10+
export const getStackBlitzEmbedIframe = (url) => {
11+
const editRegex = /(.*\/edit\/.*?)((?:\?.*$)|$)/;
12+
const regexResults = editRegex.exec(url);
13+
const base = regexResults[1];
14+
let queryStr = regexResults[2];
15+
if (queryStr) {
16+
queryStr = queryStr.replace('?', '?embed=1&');
17+
} else {
18+
queryStr = '?embed=1';
19+
}
20+
21+
return `${base}${queryStr}`;
22+
}
23+
24+
export const getHTML = (url) => {
25+
const iframeUrl = getStackBlitzEmbedIframe(url);
26+
27+
return `<iframe src="${iframeUrl}" style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;" sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"></iframe>`;
28+
};

src/transformers/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import * as PinterestTransformer from './Pinterest';
77
import * as SlidesTransformer from './Slides';
88
import * as SoundCloudTransformer from './SoundCloud';
99
import * as SpotifyTransformer from './Spotify';
10+
import * as StackBlitzTransformer from './StackBlitz';
1011
import * as StreamableTransformer from './Streamable';
1112
import * as TestingPlaygroundTransformer from './TestingPlayground';
1213
import * as TwitchTransformer from './Twitch';
@@ -23,6 +24,7 @@ export const defaultTransformers = [
2324
SlidesTransformer,
2425
SoundCloudTransformer,
2526
SpotifyTransformer,
27+
StackBlitzTransformer,
2628
StreamableTransformer,
2729
TestingPlaygroundTransformer,
2830
TwitchTransformer,

0 commit comments

Comments
 (0)