Skip to content

Commit e75d65a

Browse files
Merge branch 'develop' of https://github.com/live-codes/livecodes into i18n/develop
2 parents eab4cb1 + f46a5c6 commit e75d65a

File tree

7 files changed

+99
-47
lines changed

7 files changed

+99
-47
lines changed

src/livecodes/compiler/compile.worker.ts

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
import type TS from 'typescript';
22
import { getCompilerOptions } from '../editor/ts-compiler-options';
33
import { languages, processors } from '../languages';
4-
import type { CompileOptions, Compilers, Config, EditorLibrary, Language } from '../models';
5-
import { doOnce, objectFilter } from '../utils/utils';
4+
import type {
5+
CompileOptions,
6+
CompileResult,
7+
Compilers,
8+
Config,
9+
EditorLibrary,
10+
Language,
11+
} from '../models';
12+
import { doOnce, getErrorMessage, objectFilter } from '../utils/utils';
613
import { codeMirrorBaseUrl, comlinkBaseUrl, vendorsBaseUrl } from '../vendors';
714
import { getAllCompilers } from './get-all-compilers';
815
import type { CompilerMessage, CompilerMessageEvent, LanguageOrProcessor } from './models';
@@ -98,13 +105,16 @@ const compile = async (
98105
throw new Error('Failed to load compiler for: ' + language);
99106
}
100107

101-
let value;
108+
let value: string | CompileResult = '';
102109
try {
103110
value = await compiler(content, { config, language, baseUrl, options });
104-
} catch (err) {
111+
} catch (err: unknown) {
105112
// eslint-disable-next-line no-console
106113
console.error('Failed compiling: ' + language, err);
107-
value = content;
114+
value = {
115+
code: '',
116+
info: { errors: [getErrorMessage(err)] },
117+
};
108118
}
109119
return value || '';
110120
};

src/livecodes/core.ts

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -996,7 +996,7 @@ const getResultPage = async ({
996996
},
997997
};
998998

999-
const compileResults = await Promise.all([
999+
const [styleCompileResult, testsCompileResult] = await Promise.all([
10001000
compiler.compile(styleContent, styleLanguage, config, {
10011001
html: `${compiledMarkup}<script type="script-for-styles">${compiledScript}</script>
10021002
<script type="script-for-styles">${compileInfo.importedContent}</script>`,
@@ -1008,8 +1008,7 @@ const getResultPage = async ({
10081008
: compiler.compile(testsContent, testsLanguage, config, {})
10091009
: Promise.resolve(getCompileResult(getCache().tests?.compiled || '')),
10101010
]);
1011-
1012-
const [compiledStyle, compiledTests] = compileResults.map((result) => {
1011+
const [compiledStyle, compiledTests] = [styleCompileResult, testsCompileResult].map((result) => {
10131012
const { code, info } = getCompileResult(result);
10141013
compileInfo = {
10151014
...compileInfo,
@@ -1027,10 +1026,12 @@ const getResultPage = async ({
10271026
markup: {
10281027
...contentConfig.markup,
10291028
compiled: compiledMarkup,
1029+
modified: compiledMarkup,
10301030
},
10311031
style: {
10321032
...contentConfig.style,
10331033
compiled: compiledStyle,
1034+
modified: compiledStyle,
10341035
},
10351036
script: {
10361037
...contentConfig.script,
@@ -1045,6 +1046,7 @@ const getResultPage = async ({
10451046
compiled: compiledTests,
10461047
},
10471048
};
1049+
compiledCode.script.modified = compiledCode.script.compiled;
10481050

10491051
if (scriptType != null && scriptType !== 'module') {
10501052
singleFile = true;
@@ -1063,6 +1065,14 @@ const getResultPage = async ({
10631065

10641066
const styleOnlyUpdate = sourceEditor === 'style' && !compileInfo.cssModules;
10651067

1068+
const logError = (language: Language, errors: string[] = []) => {
1069+
errors.forEach((err) => toolsPane?.console?.error(`[${getLanguageTitle(language)}] ${err}`));
1070+
};
1071+
logError(markupLanguage, markupCompileResult.info?.errors);
1072+
logError(styleLanguage, styleCompileResult.info?.errors);
1073+
logError(scriptLanguage, scriptCompileResult.info?.errors);
1074+
logError(testsLanguage, getCompileResult(testsCompileResult).info?.errors);
1075+
10661076
if (singleFile) {
10671077
setCache({
10681078
...getCache(),
@@ -1124,17 +1134,9 @@ const flushResult = () => {
11241134
wat: ';; loading',
11251135
};
11261136

1127-
updateCache(
1128-
'markup',
1129-
compiledLanguages.markup,
1130-
loadingComments[compiledLanguages.markup] || 'html',
1131-
);
1132-
updateCache('style', compiledLanguages.style, loadingComments[compiledLanguages.style] || 'css');
1133-
updateCache(
1134-
'script',
1135-
compiledLanguages.script,
1136-
loadingComments[compiledLanguages.script] || 'javascript',
1137-
);
1137+
updateCache('markup', compiledLanguages.markup, loadingComments[compiledLanguages.markup] ?? '');
1138+
updateCache('style', compiledLanguages.style, loadingComments[compiledLanguages.style] ?? '');
1139+
updateCache('script', compiledLanguages.script, loadingComments[compiledLanguages.script] ?? '');
11381140
setCache({
11391141
...getCache(),
11401142
tests: {

src/livecodes/languages/gleam/lang-gleam-compiler.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
/* eslint-disable max-classes-per-file */
44
import type { CompilerFunction } from '../../models';
5+
import { getErrorMessage } from '../../utils/utils';
56
import { gleamBaseUrl } from '../../vendors';
67
import { getLanguageCustomSettings } from '../utils';
78
import { modules, type Modules } from './gleam-modules';
@@ -193,7 +194,10 @@ import { modules, type Modules } from './gleam-modules';
193194
} catch (error) {
194195
// eslint-disable-next-line no-console
195196
console.warn(error);
196-
return '';
197+
return {
198+
code: '',
199+
info: { errors: [getErrorMessage(error)] },
200+
};
197201
} finally {
198202
project.delete();
199203
}

src/livecodes/languages/svelte/lang-svelte-compiler.ts

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ import { compileAllBlocks } from '../../compiler/compile-blocks';
22
import { createImportMap, replaceSFCImports } from '../../compiler/import-map';
33
import { getCompileResult } from '../../compiler/utils';
44
import type { CompilerFunction, Config, Language } from '../../models';
5+
import { getErrorMessage } from '../../utils/utils';
56
import { getLanguageByAlias, getLanguageCustomSettings } from '../utils';
67

78
(self as any).createSvelteCompiler = (): CompilerFunction => {
89
const MAIN_FILE = '__LiveCodes_App__.svelte';
910
const SECONDARY_FILE = '__LiveCodes_Component__.svelte';
1011
let importedContent = '';
1112
let imports: Record<string, string> = {};
13+
let errors: string[] = [];
1214

1315
const compileSvelteSFC = async (
1416
code: string,
@@ -42,21 +44,32 @@ import { getLanguageByAlias, getLanguageCustomSettings } from '../utils';
4244
});
4345
const customSettings = getLanguageCustomSettings('svelte', config);
4446

45-
const { js } = (window as any).svelte.compile(processedCode, {
46-
css: 'injected',
47-
filename,
48-
...customSettings,
49-
});
50-
5147
if (filename === MAIN_FILE || filename === SECONDARY_FILE) {
5248
imports = createImportMap(importedContent, config);
49+
errors = [];
50+
}
51+
52+
let js: { code: string };
53+
try {
54+
const result = (window as any).svelte.compile(processedCode, {
55+
css: 'injected',
56+
filename,
57+
...customSettings,
58+
});
59+
js = result.js;
60+
} catch (err) {
61+
errors.push(getErrorMessage(err));
62+
return {
63+
code: '',
64+
info: { errors },
65+
};
5366
}
5467

5568
const compiledCode = filename === MAIN_FILE ? getMountCode(js.code) : js.code;
5669
return {
5770
code:
5871
language === 'svelte-app' ? `<script type="module">${compiledCode}</script>` : compiledCode,
59-
info: { importedContent, imports },
72+
info: { importedContent, imports, errors },
6073
};
6174
};
6275

src/livecodes/languages/vue/lang-vue-compiler.ts

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { compileInCompiler } from '../../compiler/compile-in-compiler';
33
import { createImportMap, replaceSFCImports } from '../../compiler/import-map';
44
import type { LanguageOrProcessor } from '../../compiler/models';
55
import type { CompilerFunction, Config } from '../../models';
6-
import { getRandomString, replaceAsync } from '../../utils/utils';
6+
import { getErrorMessage, getRandomString, replaceAsync } from '../../utils/utils';
77
import { getLanguageByAlias } from '../utils';
88

99
// based on:
@@ -363,35 +363,48 @@ import { getLanguageByAlias } from '../utils';
363363
}
364364

365365
return async (code, { config, language }) => {
366-
const isMainFile = config.markup.language !== 'vue-app' || language === 'vue-app';
367-
const filename = isMainFile ? MAIN_FILE : SECONDARY_FILE;
368-
const result = await compileVueSFC(code, { config, filename });
366+
try {
367+
const isMainFile = config.markup.language !== 'vue-app' || language === 'vue-app';
368+
const filename = isMainFile ? MAIN_FILE : SECONDARY_FILE;
369+
const result = await compileVueSFC(code, { config, filename });
369370

370-
if (result) {
371-
const { css, js } = result;
371+
if (result) {
372+
const { css, js } = result;
372373

373-
const injectCSS = !css.trim()
374-
? ''
375-
: `
374+
const injectCSS = !css.trim()
375+
? ''
376+
: `
376377
document.head.insertBefore(
377378
Object.assign(document.createElement('style'), { textContent: ${JSON.stringify(css)} }),
378379
document.head.getElementsByTagName('style')[0]
379380
);
380381
`;
381-
const compiledCode = js + injectCSS;
382+
const compiledCode = js + injectCSS;
383+
384+
return {
385+
code:
386+
language === 'vue-app'
387+
? `<script type="module">${compiledCode}</script>`
388+
: compiledCode,
389+
info: { importedContent, imports: createImportMap(importedContent, config), errors },
390+
};
391+
}
392+
393+
if (errors.length) {
394+
// eslint-disable-next-line no-console
395+
console.error(...errors);
396+
}
382397

398+
const empty = `export default () => {}`;
383399
return {
384-
code:
385-
language === 'vue-app' ? `<script type="module">${compiledCode}</script>` : compiledCode,
386-
info: { importedContent, imports: createImportMap(importedContent, config) },
400+
code: language === 'vue-app' ? `<script type="module">${empty}</script>` : empty,
401+
info: { errors },
402+
};
403+
} catch (err) {
404+
return {
405+
code: '',
406+
info: { errors: [...errors, getErrorMessage(err)] },
387407
};
388408
}
389-
390-
if (errors.length) {
391-
// eslint-disable-next-line no-console
392-
console.error(...errors);
393-
}
394-
395-
return '';
396409
};
397410
};

src/livecodes/utils/utils.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -643,6 +643,15 @@ export const compareObjects = /* @__PURE__ */ (
643643
return diff;
644644
};
645645

646+
export const getErrorMessage = /* @__PURE__ */ (err: unknown): string => {
647+
if (err == null) return '';
648+
if (err instanceof Error) return err.message;
649+
if (err && typeof err === 'object' && 'message' in err && typeof err.message === 'string') {
650+
return err.message;
651+
}
652+
return String(err);
653+
};
654+
646655
export const predefinedValues = {
647656
APP_VERSION: process.env.VERSION || '',
648657
SDK_VERSION: process.env.SDK_VERSION || '',

src/sdk/models.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1291,6 +1291,7 @@ export interface CompileInfo {
12911291
modifiedHTML?: string;
12921292
importedContent?: string;
12931293
imports?: Record<string, string>;
1294+
errors?: string[];
12941295
}
12951296

12961297
export interface CompileResult {

0 commit comments

Comments
 (0)