mirror of
https://github.com/coder/code-server.git
synced 2026-02-11 07:50:10 -06:00
254 lines
7.7 KiB
TypeScript
254 lines
7.7 KiB
TypeScript
import { getOptions, Options } from "../../common/util"
|
|
import "../register"
|
|
|
|
// TODO@jsjoeio: Add proper types.
|
|
type FixMeLater = any
|
|
|
|
// NOTE@jsjoeio
|
|
// This lives here ../../../lib/vscode/src/vs/base/common/platform.ts#L106
|
|
export const nlsConfigElementId = "vscode-remote-nls-configuration"
|
|
|
|
type NlsConfiguration = {
|
|
locale: string
|
|
availableLanguages: { [key: string]: string } | {}
|
|
_languagePackId?: string
|
|
_translationsConfigFile?: string
|
|
_cacheRoot?: string
|
|
_resolvedLanguagePackCoreLocation?: string
|
|
_corruptedFile?: string
|
|
_languagePackSupport?: boolean
|
|
loadBundle?: FixMeLater
|
|
}
|
|
|
|
/**
|
|
* Helper function to create the path to the bundle
|
|
* for getNlsConfiguration.
|
|
*/
|
|
export function createBundlePath(_resolvedLanguagePackCoreLocation: string | undefined, bundle: string) {
|
|
// NOTE@jsjoeio - this comment was here before me
|
|
// Refers to operating systems that use a different path separator.
|
|
// Probably just Windows but we're not sure if "/" breaks on Windows
|
|
// so we'll leave it alone for now.
|
|
// FIXME: Only works if path separators are /.
|
|
return (_resolvedLanguagePackCoreLocation || "") + "/" + bundle.replace(/\//g, "!") + ".nls.json"
|
|
}
|
|
|
|
/**
|
|
* A helper function to get the NLS Configuration settings.
|
|
*
|
|
* This is used by VSCode for localizations (i.e. changing
|
|
* the display language).
|
|
*
|
|
* Make sure to wrap this in a try/catch block when you call it.
|
|
**/
|
|
export function getNlsConfiguration(_document: Document, base: string) {
|
|
const errorMsgPrefix = "[vscode]"
|
|
const nlsConfigElement = _document?.getElementById(nlsConfigElementId)
|
|
const dataSettings = nlsConfigElement?.getAttribute("data-settings")
|
|
|
|
if (!nlsConfigElement) {
|
|
throw new Error(
|
|
`${errorMsgPrefix} Could not parse NLS configuration. Could not find nlsConfigElement with id: ${nlsConfigElementId}`,
|
|
)
|
|
}
|
|
|
|
if (!dataSettings) {
|
|
throw new Error(
|
|
`${errorMsgPrefix} Could not parse NLS configuration. Found nlsConfigElement but missing data-settings attribute.`,
|
|
)
|
|
}
|
|
|
|
const nlsConfig = JSON.parse(dataSettings) as NlsConfiguration
|
|
|
|
if (nlsConfig._resolvedLanguagePackCoreLocation) {
|
|
// NOTE@jsjoeio
|
|
// Not sure why we use Object.create(null) instead of {}
|
|
// They are not the same
|
|
// See: https://stackoverflow.com/a/15518712/3015595
|
|
// We copied this from ../../../lib/vscode/src/bootstrap.js#L143
|
|
const bundles: {
|
|
[key: string]: string
|
|
} = Object.create(null)
|
|
|
|
type LoadBundleCallback = (_: undefined, result?: string) => void
|
|
|
|
nlsConfig.loadBundle = async (bundle: string, _language: string, cb: LoadBundleCallback): Promise<void> => {
|
|
const result = bundles[bundle]
|
|
|
|
if (result) {
|
|
return cb(undefined, result)
|
|
}
|
|
|
|
try {
|
|
const path = createBundlePath(nlsConfig._resolvedLanguagePackCoreLocation, bundle)
|
|
const response = await fetch(`${base}/vscode/resource/?path=${encodeURIComponent(path)}`)
|
|
const json = await response.json()
|
|
bundles[bundle] = json
|
|
return cb(undefined, json)
|
|
} catch (error) {
|
|
return cb(error)
|
|
}
|
|
}
|
|
}
|
|
|
|
return nlsConfig
|
|
}
|
|
|
|
type GetLoaderParams = {
|
|
nlsConfig: NlsConfiguration
|
|
options: Options
|
|
_window: Window
|
|
}
|
|
|
|
/**
|
|
* Link to types in the loader source repo
|
|
* https://github.com/microsoft/vscode-loader/blob/main/src/loader.d.ts#L280
|
|
*/
|
|
type Loader = {
|
|
baseUrl: string
|
|
recordStats: boolean
|
|
// TODO@jsjoeio: There don't appear to be any types for trustedTypes yet.
|
|
trustedTypesPolicy: FixMeLater
|
|
paths: {
|
|
[key: string]: string
|
|
}
|
|
"vs/nls": NlsConfiguration
|
|
}
|
|
|
|
/**
|
|
* A helper function which creates a script url if the value
|
|
* is valid.
|
|
*
|
|
* Extracted into a function to make it easier to test
|
|
*/
|
|
export function _createScriptURL(value: string, origin: string): string {
|
|
if (value.startsWith(origin)) {
|
|
return value
|
|
}
|
|
throw new Error(`Invalid script url: ${value}`)
|
|
}
|
|
|
|
/**
|
|
* A helper function to get the require loader
|
|
*
|
|
* This used by VSCode/code-server
|
|
* to load files.
|
|
*
|
|
* We extracted the logic into a function so that
|
|
* it's easier to test.
|
|
**/
|
|
export function getConfigurationForLoader({ nlsConfig, options, _window }: GetLoaderParams) {
|
|
const loader: Loader = {
|
|
// Without the full URL VS Code will try to load file://.
|
|
baseUrl: `${window.location.origin}${options.csStaticBase}/lib/vscode/out`,
|
|
recordStats: true,
|
|
trustedTypesPolicy: (_window as FixMeLater).trustedTypes?.createPolicy("amdLoader", {
|
|
createScriptURL(value: string): string {
|
|
return _createScriptURL(value, window.location.origin)
|
|
},
|
|
}),
|
|
paths: {
|
|
"vscode-textmate": `../node_modules/vscode-textmate/release/main`,
|
|
"vscode-oniguruma": `../node_modules/vscode-oniguruma/release/main`,
|
|
xterm: `../node_modules/xterm/lib/xterm.js`,
|
|
"xterm-addon-search": `../node_modules/xterm-addon-search/lib/xterm-addon-search.js`,
|
|
"xterm-addon-unicode11": `../node_modules/xterm-addon-unicode11/lib/xterm-addon-unicode11.js`,
|
|
"xterm-addon-webgl": `../node_modules/xterm-addon-webgl/lib/xterm-addon-webgl.js`,
|
|
"tas-client-umd": `../node_modules/tas-client-umd/lib/tas-client-umd.js`,
|
|
"iconv-lite-umd": `../node_modules/iconv-lite-umd/lib/iconv-lite-umd.js`,
|
|
jschardet: `../node_modules/jschardet/dist/jschardet.min.js`,
|
|
},
|
|
"vs/nls": nlsConfig,
|
|
}
|
|
|
|
return loader
|
|
}
|
|
|
|
/**
|
|
* Sets the body background color to match the theme.
|
|
*/
|
|
export function setBodyBackgroundToThemeBackgroundColor(_document: Document, _localStorage: Storage) {
|
|
const errorMsgPrefix = "[vscode]"
|
|
const colorThemeData = _localStorage.getItem("colorThemeData")
|
|
|
|
if (!colorThemeData) {
|
|
throw new Error(
|
|
`${errorMsgPrefix} Could not set body background to theme background color. Could not find colorThemeData in localStorage.`,
|
|
)
|
|
}
|
|
|
|
let _colorThemeData
|
|
try {
|
|
// We wrap this JSON.parse logic in a try/catch
|
|
// because it can throw if the JSON is invalid.
|
|
// and instead of throwing a random error
|
|
// we can throw our own error, which will be more helpful
|
|
// to the end user.
|
|
_colorThemeData = JSON.parse(colorThemeData)
|
|
} catch {
|
|
throw new Error(
|
|
`${errorMsgPrefix} Could not set body background to theme background color. Could not parse colorThemeData from localStorage.`,
|
|
)
|
|
}
|
|
|
|
const hasColorMapProperty = Object.prototype.hasOwnProperty.call(_colorThemeData, "colorMap")
|
|
if (!hasColorMapProperty) {
|
|
throw new Error(
|
|
`${errorMsgPrefix} Could not set body background to theme background color. colorThemeData is missing colorMap.`,
|
|
)
|
|
}
|
|
|
|
const editorBgColor = _colorThemeData.colorMap["editor.background"]
|
|
|
|
if (!editorBgColor) {
|
|
throw new Error(
|
|
`${errorMsgPrefix} Could not set body background to theme background color. colorThemeData.colorMap["editor.background"] is undefined.`,
|
|
)
|
|
}
|
|
|
|
_document.body.style.background = editorBgColor
|
|
|
|
return null
|
|
}
|
|
|
|
/**
|
|
* A helper function to encapsulate all the
|
|
* logic used in this file.
|
|
*
|
|
* We purposely include all of this in a single function
|
|
* so that it's easier to test.
|
|
*/
|
|
export function main(_document: Document | undefined, _window: Window | undefined, _localStorage: Storage | undefined) {
|
|
if (!_document) {
|
|
throw new Error(`document is undefined.`)
|
|
}
|
|
|
|
if (!_window) {
|
|
throw new Error(`window is undefined.`)
|
|
}
|
|
|
|
if (!_localStorage) {
|
|
throw new Error(`localStorage is undefined.`)
|
|
}
|
|
|
|
const options = getOptions()
|
|
const nlsConfig = getNlsConfiguration(_document, options.base)
|
|
|
|
const loader = getConfigurationForLoader({
|
|
nlsConfig,
|
|
options,
|
|
_window,
|
|
})
|
|
|
|
;(self.require as unknown as Loader) = loader
|
|
|
|
setBodyBackgroundToThemeBackgroundColor(_document, _localStorage)
|
|
}
|
|
|
|
try {
|
|
main(document, window, localStorage)
|
|
} catch (error) {
|
|
console.error("[vscode] failed to initialize VS Code")
|
|
console.error(error)
|
|
}
|