Skip to content

Commit 380dd52

Browse files
authored
HTML support (codesandbox#6)
1 parent 1512e54 commit 380dd52

File tree

6 files changed

+70
-48
lines changed

6 files changed

+70
-48
lines changed

src/app/pages/Sandbox/Editor/Content/subviews/CodeEditor/index.js

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ export default class CodeEditor extends React.PureComponent {
149149
if (kind[1] === 'css') {
150150
await System.import('codemirror/mode/css/css');
151151
return 'css';
152+
} else if (kind[1] === 'html') {
153+
await System.import('codemirror/mode/htmlmixed/htmlmixed');
154+
return 'htmlmixed';
152155
}
153156
}
154157

@@ -267,16 +270,19 @@ export default class CodeEditor extends React.PureComponent {
267270
getCode = () => this.codemirror.getValue();
268271

269272
prettify = async () => {
270-
const { id, preferences } = this.props;
273+
const { id, title, preferences } = this.props;
271274
const code = this.getCode();
272-
try {
273-
const newCode = await prettify(code, preferences.lintEnabled);
275+
const mode = await this.getMode(title);
276+
if (mode === 'jsx') {
277+
try {
278+
const newCode = await prettify(code, preferences.lintEnabled);
274279

275-
if (newCode !== code) {
276-
this.props.changeCode(id, newCode);
277-
this.updateCodeMirrorCode(newCode);
278-
}
279-
} catch (e) {}
280+
if (newCode !== code) {
281+
this.props.changeCode(id, newCode);
282+
this.updateCodeMirrorCode(newCode);
283+
}
284+
} catch (e) {}
285+
}
280286
};
281287

282288
handleSaveCode = async () => {

src/app/store/entities/sandboxes/actions.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,7 @@ export default {
646646
const directories = directoriesSelector(getState());
647647
const sandbox = singleSandboxSelector(getState(), { id });
648648

649-
const createZip = await System.import('./create-zip');
649+
const createZip = await System.import('./utils/create-zip');
650650

651651
createZip.default(
652652
sandbox,
File renamed without changes.

src/app/store/entities/sandboxes/create-zip.js renamed to src/app/store/entities/sandboxes/utils/create-zip.js

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
import JSZip from 'jszip';
33
import { saveAs } from 'file-saver';
44

5-
import type { Sandbox } from './entity';
6-
import type { Module } from './modules/entity';
7-
import type { Directory } from './directories/entity';
5+
import type { Sandbox } from '../entity';
6+
import type { Module } from '../modules/entity';
7+
import type { Directory } from '../directories/entity';
88

99
import README from './README.md';
1010
import favicon from '!base64-loader!./favicon.ico';
@@ -25,7 +25,19 @@ function getResourceTag(resource: string) {
2525
return '';
2626
}
2727

28-
const getHTML = resources => `<!doctype html>
28+
function getIndexHtmlBody(modules) {
29+
const indexHtmlModule = modules.find(
30+
m => m.title === 'index.html' && m.directoryShortid == null
31+
);
32+
33+
if (indexHtmlModule) {
34+
return indexHtmlModule.code || '';
35+
}
36+
37+
return `<div id="root"></div>`;
38+
}
39+
40+
const getHTML = (modules, resources) => `<!doctype html>
2941
<html lang="en">
3042
<head>
3143
<meta charset="utf-8">
@@ -44,17 +56,7 @@ const getHTML = resources => `<!doctype html>
4456
${resources.map(getResourceTag).join('\n')}
4557
</head>
4658
<body>
47-
<div id="root"></div>
48-
<!--
49-
This HTML file is a template.
50-
If you open it directly in the browser, you will see an empty page.
51-
52-
You can add webfonts, meta tags, or analytics to this file.
53-
The build step will place the bundled scripts into the <body> tag.
54-
55-
To begin the development, run \`npm start\`.
56-
To create a production bundle, use \`npm run build\`.
57-
-->
59+
${getIndexHtmlBody(modules)}
5860
</body>
5961
</html>`;
6062

@@ -127,19 +129,21 @@ export default (async function createZip(
127129
const src = zip.folder('src');
128130
modules
129131
.filter(x => x.directoryShortid == null)
132+
.filter(x => x.title !== 'index.html') // This will be included in the body
130133
.forEach(x => src.file(x.title, x.code));
131134

132135
directories
133136
.filter(x => x.directoryShortid == null)
134137
.forEach(x => createDirectoryWithFiles(modules, directories, x, src));
135138

136139
const publicFolder = zip.folder('public');
137-
publicFolder.file('index.html', getHTML(sandbox.externalResources));
138140

139141
publicFolder.file('favicon.ico', favicon, {
140142
base64: true,
141143
});
142144

145+
publicFolder.file('index.html', getHTML(modules, sandbox.externalResources));
146+
143147
if (
144148
!modules.find(x => x.directoryShortid == null && x.title === 'README.md')
145149
) {
File renamed without changes.

src/sandbox/index.js

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,26 @@ let fetching = false;
1919
let url = null;
2020

2121
async function addDependencyBundle() {
22-
const script = document.createElement('script');
23-
script.setAttribute('src', url);
24-
script.setAttribute('async', false);
25-
document.head.appendChild(script);
22+
if (url !== '') {
23+
const script = document.createElement('script');
24+
script.setAttribute('src', url);
25+
script.setAttribute('async', false);
26+
document.head.appendChild(script);
27+
28+
while (window.dependencies == null) {
29+
await delay(100);
30+
}
31+
}
32+
}
2633

27-
while (window.dependencies == null) {
28-
await delay(100);
34+
function getIndexHtml(modules) {
35+
const module = modules.find(
36+
m => m.title === 'index.html' && m.directoryShortid == null
37+
);
38+
if (module) {
39+
return module.code;
2940
}
41+
return '<div id="root"></div>';
3042
}
3143

3244
async function compile(message) {
@@ -52,24 +64,11 @@ async function compile(message) {
5264
window.parent.postMessage('Ready!', host);
5365
return;
5466
}
55-
56-
// initiate boilerplates
57-
if (
58-
boilerplates.length !== 0 &&
59-
getBoilerplates().length === 0 &&
60-
manifest != null
61-
) {
62-
try {
63-
evalBoilerplates(boilerplates, modules, directories, manifest);
64-
} catch (e) {
65-
console.log("Couldn't load all boilerplates");
66-
}
67-
}
68-
6967
handleExternalResources(externalResources);
7068

7169
try {
72-
document.body.innerHTML = '<div id="root"></div>';
70+
const html = getIndexHtml(modules);
71+
document.body.innerHTML = html;
7372
deleteCache(sandboxId, changedModule);
7473

7574
const evalled = evalModule(
@@ -79,13 +78,26 @@ async function compile(message) {
7978
directories,
8079
manifest
8180
);
82-
const domChanged = document.body.innerHTML !== '<div id="root"></div>';
81+
const domChanged = document.body.innerHTML !== html;
8382

84-
if (!domChanged) {
83+
if (!domChanged && !module.title.endsWith('.html')) {
8584
const isReact = module.code.includes('React');
8685
const functionName = evalled.default ? evalled.default.name : '';
8786

8887
if (isReact) {
88+
// initiate boilerplates
89+
if (
90+
boilerplates.length !== 0 &&
91+
getBoilerplates().length === 0 &&
92+
manifest != null
93+
) {
94+
try {
95+
evalBoilerplates(boilerplates, modules, directories, manifest);
96+
} catch (e) {
97+
console.log("Couldn't load all boilerplates");
98+
}
99+
}
100+
89101
const boilerplate = findBoilerplate(module);
90102
if (boilerplate) {
91103
try {

0 commit comments

Comments
 (0)