Skip to content

Commit

Permalink
Load Monaco Files From Node Modules Folder (#3032)
Browse files Browse the repository at this point in the history
Load Monaco Files From Node Modules Folder
  • Loading branch information
jameskerr authored Mar 28, 2024
1 parent 5e8e414 commit d012848
Show file tree
Hide file tree
Showing 9 changed files with 78 additions and 21 deletions.
3 changes: 2 additions & 1 deletion apps/zui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
"release-insiders": "electron-builder --config electron-builder-insiders.json --publish always"
},
"dependencies": {
"keytar": "^7.7.0"
"keytar": "^7.7.0",
"monaco-editor": "^0.47.0"
},
"devDependencies": {
"@babel/core": "^7.17.9",
Expand Down
2 changes: 1 addition & 1 deletion apps/zui/src/components/zed-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export function ZedEditor(props: {
minimap: {enabled: false},
renderLineHighlight: "none",
renderControlCharacters: false,
fontSize: "14px",
fontSize: 14,
fontFamily: "var(--mono-font)",
fontVariations: "inherit",
lineNumbersMinChars: 4,
Expand Down
17 changes: 17 additions & 0 deletions apps/zui/src/electron/protocols/asset-server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {app, net} from "electron"
import path from "node:path"
import {pathToFileURL} from "node:url"

export class AssetServer {
fromNodeModules(relativePath: string) {
const file = require.resolve(relativePath)
const url = pathToFileURL(file).toString()
return net.fetch(url, {bypassCustomProtocolHandlers: true})
}

fromPublic(relativeUrl: string) {
const file = path.join(app.getAppPath(), "out", relativeUrl)
const url = pathToFileURL(file).toString()
return net.fetch(url, {bypassCustomProtocolHandlers: true})
}
}
14 changes: 14 additions & 0 deletions apps/zui/src/electron/protocols/asset-url.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {AssetUrl} from "./asset-url"

test("node module asset", () => {
const asset = new AssetUrl(
"app-asset://zui/node_modules/monaco/worker.js#worker"
)
expect(asset.relativeUrl).toBe("monaco/worker.js")
expect(asset.isNodeModule).toBe(true)
})

test("public asset", () => {
const asset = new AssetUrl("app-asset://zui/search.html?id=123&name=abc")
expect(asset.relativeUrl).toBe("search.html")
})
19 changes: 19 additions & 0 deletions apps/zui/src/electron/protocols/asset-url.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export class AssetUrl {
url: URL

constructor(url: string) {
this.url = new URL(url)
}

get isNodeModule() {
return this.url.pathname.startsWith("/node_modules")
}

get relativeUrl() {
if (this.isNodeModule) {
return this.url.pathname.replace("/node_modules/", "")
} else {
return this.url.pathname.replace(/^\//, "")
}
}
}
29 changes: 11 additions & 18 deletions apps/zui/src/electron/run-main/run-protocol-handlers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {app, protocol, net} from "electron"
import path from "path"
import {pathToFileURL} from "url"
import {app, protocol} from "electron"
import {AssetUrl} from "../protocols/asset-url"
import {AssetServer} from "../protocols/asset-server"

protocol.registerSchemesAsPrivileged([
{
Expand All @@ -10,24 +10,17 @@ protocol.registerSchemesAsPrivileged([
])

export function runProtocolHandlers() {
app.whenReady().then(() => {
protocol.interceptFileProtocol("file", (request, callback) => {
const url = new URL(request.url)
const rootPath = path.join(__dirname, "..", "out")
const relPath = url.pathname
const absPath = path.join(rootPath, relPath)
callback(absPath)
})
const server = new AssetServer()

app.whenReady().then(() => {
protocol.handle("app-asset", (request) => {
const {host, pathname, href} = new URL(request.url)
if (host === "node_modules") {
const path = pathname.slice(1)
const file = require.resolve(path)
const url = pathToFileURL(file).toString()
return net.fetch(url, {bypassCustomProtocolHandlers: true})
const asset = new AssetUrl(request.url)

if (asset.isNodeModule) {
return server.fromNodeModules(asset.relativeUrl)
} else {
return server.fromPublic(asset.relativeUrl)
}
throw new Error("Unknown App Asset " + href)
})
})
}
3 changes: 2 additions & 1 deletion apps/zui/src/electron/windows/zui-window.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export abstract class ZuiWindow {
...getWindowDimens(this.dimens, pickDimens(this.options), getDisplays()),
webPreferences: {
preload: path.join(__dirname, "../build/preload.js"),
webSecurity: env.isRelease,
},
})
this.touch()
Expand Down Expand Up @@ -69,7 +70,7 @@ export abstract class ZuiWindow {
this.beforeLoad()
const url = env.isDevelopment
? `http://localhost:4567${this.path}?id=${this.id}&name=${this.name}`
: `file://${this.path}.html?id=${this.id}&name=${this.name}`
: `app-asset://zui${this.path}.html?id=${this.id}&name=${this.name}`
return this.ref.loadURL(url)
}

Expand Down
4 changes: 4 additions & 0 deletions apps/zui/src/js/initializers/init-monaco.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import {tokens} from "src/core/zed-syntax"
import {loader} from "@monaco-editor/react"

loader.config({
paths: {vs: "app-asset://zui/node_modules/monaco-editor/min/vs"},
})

export async function initializeMonaco() {
if (globalThis.env.isTest) return // Only works in a browser environment
try {
Expand Down
8 changes: 8 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -14140,6 +14140,13 @@ __metadata:
languageName: node
linkType: hard

"monaco-editor@npm:^0.47.0":
version: 0.47.0
resolution: "monaco-editor@npm:0.47.0"
checksum: a1c5fe6a0d71214aa2fd4fd635f89a7df6ad599e4e01492a268eb70a456e7a29dfa301324e00b577eaf9fa69813b8a28924980ab8457d89faf14d13fcbbc2d6e
languageName: node
linkType: hard

"mousetrap@npm:^1.6.5":
version: 1.6.5
resolution: "mousetrap@npm:1.6.5"
Expand Down Expand Up @@ -19356,6 +19363,7 @@ __metadata:
memoize-one: ^6.0.0
moment: ^2.27.0
moment-timezone: ^0.5.31
monaco-editor: ^0.47.0
mousetrap: ^1.6.5
msw: ^0.36.8
next: ^13.3.0
Expand Down

0 comments on commit d012848

Please sign in to comment.