Skip to content

Commit

Permalink
Merge pull request #134 from gridaco/staging
Browse files Browse the repository at this point in the history
APR Release #1
  • Loading branch information
softmarshmallow authored Apr 11, 2022
2 parents a0dd9fd + 6155b95 commit 1a96a48
Show file tree
Hide file tree
Showing 102 changed files with 4,940 additions and 3,370 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,8 @@ export function CanvasEventTarget({
overflow: "hidden",
touchAction: "none",
cursor: isSpacebarPressed ? "grab" : "default",
userSelect: "none",
WebkitUserSelect: "none",
}}
id="gesture-event-listener"
ref={interactionEventTargetRef}
Expand Down
6 changes: 6 additions & 0 deletions editor-packages/editor-services-dart/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "@code-editor/dart-services",
"description": "dart build services for flutter framework",
"version": "0.0.0",
"private": false
}
5 changes: 5 additions & 0 deletions editor-packages/editor-services-esbuild/contributing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# About esbuild-wasm version.

The wasm file downloaded over network must match the locally installed esbuild-wasm package, so always use exact version. (not ^v, ^v0.0.0, etc.)

currently using `0.14.34`
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.out.js
78 changes: 78 additions & 0 deletions editor-packages/editor-services-esbuild/fetch.plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { OnLoadResult, PluginBuild } from "esbuild-wasm";
import axios from "axios";
import localforage from "localforage";
import { normalizeCss } from ".";

const fileCache = localforage.createInstance({
name: "filecache",
});

export const fetchPlugin = (
inputCode: string,
lang: OnLoadResult["loader"]
) => ({
name: "fetch-plugin",

setup(build: PluginBuild) {
build.onLoad({ filter: /^index\.js$/ }, () => {
return {
loader: lang,
contents: inputCode,
};
});

build.onLoad({ filter: /.*/ }, async (args: any) => {
/**
* Check if module is already in filecache
* if yes? return it immediately
*
* if not, fetch it from unpkg and cache it
* and return the result
*/
const cachedResult = await fileCache.getItem<OnLoadResult>(args.path);

if (cachedResult) {
return cachedResult;
}

return null;
});

build.onLoad({ filter: /.css$/ }, async (args: any) => {
const { data, request } = await axios.get(args.path);

const contents = normalizeCss(data);

const result: OnLoadResult = {
loader: "jsx",
contents,
resolveDir: new URL("./", request.responseURL).pathname,
};

await fileCache.setItem(args.path, result);

return result;
});

build.onLoad({ filter: /.*/ }, async (args: any) => {
const { data, request } = await axios.get(args.path);

const result: OnLoadResult = {
loader: "jsx",
contents: data,
resolveDir: new URL("./", request.responseURL).pathname,
};

await fileCache.setItem(args.path, result);

return result;
});
},
});

// const libSource = ReactTypes.toString()

// const libUri = "ts:filename/facts.d.ts";
// monaco.languages.typescript.javascriptDefaults.addExtraLib(libSource, libUri);

// monaco.editor.createModel(libSource, "typescript", monaco.Uri.parse(libUri));
120 changes: 120 additions & 0 deletions editor-packages/editor-services-esbuild/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { Monaco } from "@monaco-editor/react";
import { nanoid } from "nanoid";
import { build, initialize, Loader } from "esbuild-wasm";
import { fetchPlugin } from "./fetch.plugin";
import { unpkgPathPlugin } from "./unpkg-path.plugin";

declare const window: {
monaco: Monaco;
};

let serviceLoaded: boolean | null = null;

const bundler = async (rawCode: string, lang: Loader) => {
if (!serviceLoaded) {
await initialize({
wasmURL: "https://unpkg.com/[email protected]/esbuild.wasm",
worker: true,
});
console.log("esbuild-wasm initialized");
serviceLoaded = true;
}

try {
const result = await build({
entryPoints: ["index.js"],
bundle: true,
write: false,
metafile: true,
legalComments: "none",
plugins: [unpkgPathPlugin(), fetchPlugin(rawCode, lang)],
define: {
"process.env.NODE_ENV": `"production"`,
global: "window",
},
});

const imports = result.metafile?.inputs["a:index.js"].imports
.map((el) => el.path.replace("a:https://unpkg.com/", ""))
.filter((e) => !e.includes("/"));

loadTypes(imports);

// console.log("esbuild result: ", result);

return { code: result.outputFiles[0].text, err: null };
} catch (error: any) {
console.error("esbuild error: ", error);
return {
code: null,
err: { method: "error", data: [error.message], id: nanoid() },
};
}
};

export const normalizeCss = (data: string) => {
/**
* Function to remove any new lines, quotes from imported css packages.
*/
const escaped = data
.replace(/\n/g, "")
.replace(/"/g, '\\"')
.replace(/'/g, "\\'");
return `const style = document.createElement('style')
style.innerText = '${escaped}';
document.head.appendChild(style)`;
};

export default bundler;

let typesWorker;

const loadTypes = (types) => {
const disposables: any = [];
const monaco = window && window.monaco;

const dependencies = types.map((e) => ({ name: e, version: "latest" })) || [];

if (!typesWorker) {
typesWorker = new Worker(
new URL("./workers/fetch-types.worker.js", import.meta.url)
);
}

dependencies.forEach((dep) => {
typesWorker.postMessage({
name: dep.name,
version: dep.version,
});
});

typesWorker.addEventListener("message", (event) => {
// name,
// version,
// typings: result,
const key = `node_modules/${event.data.name}/index.d.ts`;
const source = event.data.typings[key];

// const path = `${MONACO_LIB_PREFIX}${event.data.name}`;
const libUri = `file:///node_modules/@types/${event.data.name}/index.d.ts`;

disposables.push(
monaco.languages.typescript.javascriptDefaults.addExtraLib(source, libUri)
);
disposables.push(
monaco.languages.typescript.typescriptDefaults.addExtraLib(source, libUri)
);

// When resolving definitions and references, the editor will try to use created models.
// Creating a model for the library allows "peek definition/references" commands to work with the library.
});

return {
dispose() {
disposables.forEach((d) => d.dispose());
if (typesWorker) {
typesWorker.terminate();
}
},
};
};
14 changes: 14 additions & 0 deletions editor-packages/editor-services-esbuild/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "@code-editor/esbuild-services",
"version": "0.0.0",
"private": false,
"dependencies": {
"esbuild-wasm": "0.14.34",
"localforage": "^1.10.0"
},
"peerDependencies": {
"@monaco-editor/react": "^4.4.1",
"axios": "^0.26.1",
"nanoid": "^3.3.2"
}
}
36 changes: 36 additions & 0 deletions editor-packages/editor-services-esbuild/unpkg-path.plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { PluginBuild } from "esbuild-wasm";

const unpkg_path = "https://unpkg.com";

export const unpkgPathPlugin = () => ({
name: "unpkg-path-plugin",
setup(build: PluginBuild) {
/**
* Resolve the entry file eg. `index.js`
*/
build.onResolve({ filter: /^index\.js$/ }, (args: any) => {
return { path: args.path, namespace: "a" };
});

/**
* Resolve relative modules imports
*/
build.onResolve({ filter: /^\.+\// }, (args: any) => {
const url = new URL(args.path, unpkg_path + args.resolveDir + "/").href;
return {
namespace: "a",
path: url,
};
});

/**
* Resolve main module files
*/
build.onResolve({ filter: /.*/ }, async (args: any) => {
return {
namespace: "a",
path: new URL(args.path, unpkg_path + "/").href,
};
});
},
});
Loading

1 comment on commit 1a96a48

@vercel
Copy link

@vercel vercel bot commented on 1a96a48 Apr 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.