Compare commits
4 Commits
92115d3faa
...
254c5ab48f
| Author | SHA1 | Date | |
|---|---|---|---|
|
254c5ab48f
|
|||
|
89cf48e449
|
|||
|
d6d5cd927c
|
|||
|
72ab390756
|
@@ -2,7 +2,7 @@ import MonacoEditor from '@monaco-editor/react'
|
|||||||
import { Loader } from 'esbuild-wasm'
|
import { Loader } from 'esbuild-wasm'
|
||||||
import '@/components/Playground/Output/Transform/transform.scss'
|
import '@/components/Playground/Output/Transform/transform.scss'
|
||||||
import { IFile, ITheme } from '@/components/Playground/shared'
|
import { IFile, ITheme } from '@/components/Playground/shared'
|
||||||
import { cssToJs, jsonToJs, addReactImport } from '@/components/Playground/files'
|
import { cssToJs, jsonToJs } from '@/components/Playground/files'
|
||||||
import Compiler from '@/components/Playground/compiler'
|
import Compiler from '@/components/Playground/compiler'
|
||||||
import { MonacoEditorConfig } from '@/components/Playground/CodeEditor/Editor/monacoConfig'
|
import { MonacoEditorConfig } from '@/components/Playground/CodeEditor/Editor/monacoConfig'
|
||||||
|
|
||||||
@@ -16,12 +16,7 @@ const Transform = ({ file, theme }: OutputProps) => {
|
|||||||
const [errorMsg, setErrorMsg] = useState('')
|
const [errorMsg, setErrorMsg] = useState('')
|
||||||
|
|
||||||
const compile = (code: string, loader: Loader) => {
|
const compile = (code: string, loader: Loader) => {
|
||||||
let _code = code
|
Compiler?.transform(code, loader)
|
||||||
if (['jsx', 'tsx'].includes(loader)) {
|
|
||||||
_code = addReactImport(code)
|
|
||||||
}
|
|
||||||
|
|
||||||
Compiler?.transform(_code, loader)
|
|
||||||
.then((value) => {
|
.then((value) => {
|
||||||
setCompiledCode(value.code)
|
setCompiledCode(value.code)
|
||||||
setErrorMsg('')
|
setErrorMsg('')
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import esbuild, { Loader, OnLoadArgs, Plugin, PluginBuild } from 'esbuild-wasm'
|
import esbuild, { Loader, OnLoadArgs, Plugin, PluginBuild } from 'esbuild-wasm'
|
||||||
import localforage from 'localforage'
|
import localforage from 'localforage'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { IFiles, IImportMap } from '@/components/Playground/shared'
|
import { IFile, IFiles, IImportMap } from '@/components/Playground/shared'
|
||||||
import { addReactImport, cssToJs, jsonToJs } from '@/components/Playground/files'
|
import { addReactImport, cssToJs, jsonToJs } from '@/components/Playground/files'
|
||||||
|
|
||||||
class Compiler {
|
class Compiler {
|
||||||
@@ -61,7 +61,7 @@ class Compiler {
|
|||||||
format: 'esm',
|
format: 'esm',
|
||||||
metafile: true,
|
metafile: true,
|
||||||
write: false,
|
write: false,
|
||||||
plugins: [this.fileResolverPlugin(files, importMap, entryPoint)]
|
plugins: [this.fileResolverPlugin(files, importMap)]
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -69,54 +69,16 @@ class Compiler {
|
|||||||
void esbuild.stop()
|
void esbuild.stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fileResolverPlugin = (
|
private fileResolverPlugin = (files: IFiles, importMap: IImportMap): Plugin => ({
|
||||||
files: IFiles,
|
|
||||||
importMap: IImportMap,
|
|
||||||
entryPoint: string
|
|
||||||
): Plugin => ({
|
|
||||||
name: 'file-resolver-plugin',
|
name: 'file-resolver-plugin',
|
||||||
setup: (build: PluginBuild) => {
|
setup: (build: PluginBuild) => {
|
||||||
build.onResolve({ filter: /.*/ }, (args: esbuild.OnResolveArgs) => {
|
build.onResolve({ filter: /.*/ }, (args: esbuild.OnResolveArgs) => {
|
||||||
if (entryPoint === args.path) {
|
if (args.kind === 'entry-point') {
|
||||||
return {
|
return {
|
||||||
namespace: 'OxygenToolbox',
|
namespace: 'oxygen',
|
||||||
path: args.path
|
path: args.path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (args.path.startsWith('./') && files[args.path.substring(2)]) {
|
|
||||||
return {
|
|
||||||
namespace: 'OxygenToolbox',
|
|
||||||
path: args.path.substring(2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (args.path.startsWith('./') && files[`${args.path.substring(2)}.tsx`]) {
|
|
||||||
return {
|
|
||||||
namespace: 'OxygenToolbox',
|
|
||||||
path: `${args.path.substring(2)}.tsx`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (args.path.startsWith('./') && files[`${args.path.substring(2)}.jsx`]) {
|
|
||||||
return {
|
|
||||||
namespace: 'OxygenToolbox',
|
|
||||||
path: `${args.path.substring(2)}.jsx`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (args.path.startsWith('./') && files[`${args.path.substring(2)}.ts`]) {
|
|
||||||
return {
|
|
||||||
namespace: 'OxygenToolbox',
|
|
||||||
path: `${args.path.substring(2)}.ts`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (args.path.startsWith('./') && files[`${args.path.substring(2)}.js`]) {
|
|
||||||
return {
|
|
||||||
namespace: 'OxygenToolbox',
|
|
||||||
path: `${args.path.substring(2)}.js`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (/\.\/.*\.css/.test(args.path) && !args.resolveDir) {
|
|
||||||
throw Error(`Css '${args.path}' not found`)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (/^https?:\/\/.*/.test(args.path)) {
|
if (/^https?:\/\/.*/.test(args.path)) {
|
||||||
return {
|
return {
|
||||||
namespace: 'default',
|
namespace: 'default',
|
||||||
@@ -125,10 +87,20 @@ class Compiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
args.path.includes('./') ||
|
args.path.startsWith('./') &&
|
||||||
args.path.includes('../') ||
|
(!args.resolveDir.length || args.resolveDir in files)
|
||||||
args.path.startsWith('/')
|
|
||||||
) {
|
) {
|
||||||
|
const suffix = ['', '.tsx', '.jsx', '.ts', '.js'].find((suffix) => {
|
||||||
|
return files[`${args.path.substring(2)}${suffix}`]
|
||||||
|
})
|
||||||
|
if (suffix !== undefined) {
|
||||||
|
return {
|
||||||
|
namespace: 'oxygen',
|
||||||
|
path: `${args.path.substring(2)}${suffix}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (['./', '../', '/'].some((prefix) => args.path.startsWith(prefix))) {
|
||||||
return {
|
return {
|
||||||
namespace: 'default',
|
namespace: 'default',
|
||||||
path: new URL(args.path, args.resolveDir.substring(1)).href
|
path: new URL(args.path, args.resolveDir.substring(1)).href
|
||||||
@@ -139,16 +111,26 @@ class Compiler {
|
|||||||
let tempPath = args.path
|
let tempPath = args.path
|
||||||
while (!path && tempPath.includes('/')) {
|
while (!path && tempPath.includes('/')) {
|
||||||
tempPath = tempPath.substring(0, tempPath.lastIndexOf('/'))
|
tempPath = tempPath.substring(0, tempPath.lastIndexOf('/'))
|
||||||
path = args.path.replace(tempPath, importMap.imports[tempPath])
|
if (importMap.imports[tempPath]) {
|
||||||
|
const suffix = args.path.replace(tempPath, '')
|
||||||
|
const importUrl = new URL(importMap.imports[tempPath])
|
||||||
|
path = `${importUrl.origin}${importUrl.pathname}${suffix}${importUrl.search}`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!path) {
|
if (!path) {
|
||||||
throw Error(`Import '${args.path}' not found in Import Map`)
|
throw Error(`Import '${args.path}' not found in Import Map`)
|
||||||
}
|
}
|
||||||
|
const pathUrl = new URL(path)
|
||||||
|
const externals = pathUrl.searchParams.get('external')?.split(',') ?? []
|
||||||
|
Object.keys(importMap.imports).forEach((item) => {
|
||||||
|
if (!(item in externals)) {
|
||||||
|
externals.push(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
pathUrl.searchParams.set('external', externals.join(','))
|
||||||
return {
|
return {
|
||||||
namespace: 'default',
|
namespace: 'default',
|
||||||
path
|
path: pathUrl.href
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -168,40 +150,28 @@ class Compiler {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
build.onLoad({ namespace: 'oxygen', filter: /.*/ }, (args: OnLoadArgs) => {
|
||||||
|
let file: IFile | undefined
|
||||||
|
|
||||||
|
void ['', '.tsx', '.jsx', '.ts', '.js'].forEach((suffix) => {
|
||||||
|
file = file || files[`${args.path}${suffix}`]
|
||||||
|
})
|
||||||
|
if (file) {
|
||||||
|
return {
|
||||||
|
loader: (() => {
|
||||||
|
switch (file.language) {
|
||||||
|
case 'javascript':
|
||||||
|
return 'jsx'
|
||||||
|
default:
|
||||||
|
return 'tsx'
|
||||||
|
}
|
||||||
|
})(),
|
||||||
|
contents: addReactImport(file.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
build.onLoad({ filter: /.*/ }, async (args: OnLoadArgs) => {
|
build.onLoad({ filter: /.*/ }, async (args: OnLoadArgs) => {
|
||||||
if (entryPoint === args.path) {
|
|
||||||
return {
|
|
||||||
loader: 'tsx',
|
|
||||||
contents: addReactImport(files[entryPoint].value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (files[args.path]) {
|
|
||||||
const contents = addReactImport(files[args.path].value)
|
|
||||||
if (args.path.endsWith('.jsx')) {
|
|
||||||
return {
|
|
||||||
loader: 'jsx',
|
|
||||||
contents
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (args.path.endsWith('.ts')) {
|
|
||||||
return {
|
|
||||||
loader: 'ts',
|
|
||||||
contents
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (args.path.endsWith('.js')) {
|
|
||||||
return {
|
|
||||||
loader: 'js',
|
|
||||||
contents
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
loader: 'tsx',
|
|
||||||
contents
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const cached = await this.fileCache.getItem<esbuild.OnLoadResult>(args.path)
|
const cached = await this.fileCache.getItem<esbuild.OnLoadResult>(args.path)
|
||||||
|
|
||||||
if (cached) {
|
if (cached) {
|
||||||
@@ -210,9 +180,9 @@ class Compiler {
|
|||||||
|
|
||||||
const axiosResponse = await axios.get<string>(args.path)
|
const axiosResponse = await axios.get<string>(args.path)
|
||||||
const result: esbuild.OnLoadResult = {
|
const result: esbuild.OnLoadResult = {
|
||||||
loader: 'jsx',
|
loader: 'js',
|
||||||
contents: axiosResponse.data,
|
contents: axiosResponse.data,
|
||||||
resolveDir: (axiosResponse.request as XMLHttpRequest).responseURL
|
resolveDir: args.path
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.fileCache.setItem(args.path, result)
|
await this.fileCache.setItem(args.path, result)
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ export const cssToJs = (file: IFile) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const addReactImport = (code: string) => {
|
export const addReactImport = (code: string) => {
|
||||||
if (!/import\s+React/g.test(code)) {
|
if (!/^\s*import\s+React\s+/g.test(code)) {
|
||||||
return `import React from 'react';\n${code}`
|
return `import React from 'react';\n${code}`
|
||||||
}
|
}
|
||||||
return code
|
return code
|
||||||
|
|||||||
Reference in New Issue
Block a user