@nteract/monaco-editor
Version:
A React component for the monaco editor, tailored for nteract
131 lines (116 loc) • 4.16 kB
text/typescript
import { Uri } from "monaco-editor/esm/vs/editor/editor.api";
import * as monaco from "monaco-editor/esm/vs/editor/editor.api";
/**
* Common Uri identifiers
*/
enum Identifiers {
cellUriMarker = "cell",
notebookUriMarker = "notebook"
}
/**
* Map of language id to file extension.
*/
const languageToExtensionMap = new Map<string, string>();
/**
* Document Monaco Uri helper to support conversions/detection for notebook and cells.
*/
export class DocumentUri {
/**
* Checks if uri represents a document.
* @param uri Uri to validate.
*/
static isDocument(uri: Uri): boolean {
// Remove file extension if it exists and then check if uri path ends with the notebook marker.
const path = uri.path.replace(/\.[^\/.]+$/, "");
return !!(path && path.endsWith(`/${Identifiers.notebookUriMarker}`));
}
/**
* Checks if uri represents a cell.
* @param uri Uri to validate.
*/
static isCell(uri: Uri): boolean {
// Remove file extension if it exists and then check if uri path ends with the cell marker.
const path = uri.path.replace(/\.[^\/.]+$/, "");
return !!(path && path.endsWith(`/${Identifiers.cellUriMarker}`));
}
/**
* Get document id from document uri.
* @param uri Uri of cell.
*/
static getDocumentIdFromDocumentUri(uri: Uri): string | undefined {
if (DocumentUri.isDocument(uri)) {
const tokens = uri.path.split("/");
// Document uri path is in the format of "/<document_id>/notebook.<file_extension>" so we check the length
// of the split is 3 tokens and grab the 2nd token (document id) which is index 1.
if (tokens.length === 3) {
return tokens[1];
}
}
return undefined;
}
/**
* Get document id from cell uri.
* @param uri Uri of cell.
*/
static getDocumentIdFromCellUri(uri: Uri): string | undefined {
if (DocumentUri.isCell(uri)) {
const tokens = uri.path.split("/");
// Cell uri path is in the format of "/<document_id>/<cell_id>/cell.<file_extension>" so we check the length
// of the split is 4 tokens and grab the 2nd token (document id) which is index 1.
if (tokens.length === 4) {
return tokens[1];
}
}
return undefined;
}
/**
* Get cell id from cell uri.
* @param uri Uri of cell.
*/
static getCellIdFromCellUri(uri: Uri): string | undefined {
if (DocumentUri.isCell(uri)) {
const tokens = uri.path.split("/");
// Cell uri path is in the format of "/<document_id>/<cell_id>/cell.<file_extension>" so we check the length
// of the split is 4 tokens and grab the 3rd token (cell id) which is index 2.
if (tokens.length === 4) {
return tokens[2];
}
}
return undefined;
}
/**
* Create a document uri.
* @param id Document id.
*/
static createDocumentUri(id: string, languageId: string): Uri {
const fileExtension = DocumentUri.getFileExtension(languageId);
return Uri.file(`${id}/${Identifiers.notebookUriMarker}${fileExtension}`);
}
/**
* Create a cell uri.
* @param documentId Document id.
* @param cellId Cell id.
*/
static createCellUri(documentId: string, cellId: string, languageId: string): Uri {
const fileExtension = DocumentUri.getFileExtension(languageId);
return Uri.file(`${documentId}/${cellId}/${Identifiers.cellUriMarker}${fileExtension}`);
}
/**
* Get file extension for language. If no extension exist then empty string is returned.
* @param languageId Language id.
*/
private static getFileExtension(languageId: string) {
if (!languageToExtensionMap.has(languageId)) {
monaco.languages.getLanguages().forEach((metadata) => {
languageToExtensionMap.set(
// Language id
metadata.id,
// File extension if it exists. If more than one file extension exists then take the first one
// as it's the more important version compared to the rest in the list.
metadata.extensions && metadata.extensions.length > 0 ? metadata.extensions[0] : ""
);
});
}
return languageToExtensionMap.get(languageId) || "";
}
}