Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/services/notebook/common/notebookDocumentService.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { VSBuffer, decodeBase64, encodeBase64 } from '../../../../base/common/buffer.js';
7
import { ResourceMap } from '../../../../base/common/map.js';
8
import { Schemas } from '../../../../base/common/network.js';
9
import { URI } from '../../../../base/common/uri.js';
10
import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js';
11
import { createDecorator } from '../../../../platform/instantiation/common/instantiation.js';
12
13
export const INotebookDocumentService = createDecorator<INotebookDocumentService>('notebookDocumentService');
14
15
export interface INotebookDocument {
16
readonly uri: URI;
17
getCellIndex(cellUri: URI): number | undefined;
18
}
19
20
const _lengths = ['W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f'];
21
const _padRegexp = new RegExp(`^[${_lengths.join('')}]+`);
22
const _radix = 7;
23
export function parse(cell: URI): { notebook: URI; handle: number } | undefined {
24
if (cell.scheme !== Schemas.vscodeNotebookCell) {
25
return undefined;
26
}
27
28
const idx = cell.fragment.indexOf('s');
29
if (idx < 0) {
30
return undefined;
31
}
32
33
const handle = parseInt(cell.fragment.substring(0, idx).replace(_padRegexp, ''), _radix);
34
const _scheme = decodeBase64(cell.fragment.substring(idx + 1)).toString();
35
36
if (isNaN(handle)) {
37
return undefined;
38
}
39
return {
40
handle,
41
notebook: cell.with({ scheme: _scheme, fragment: null })
42
};
43
}
44
45
export function generate(notebook: URI, handle: number): URI {
46
47
const s = handle.toString(_radix);
48
const p = s.length < _lengths.length ? _lengths[s.length - 1] : 'z';
49
50
const fragment = `${p}${s}s${encodeBase64(VSBuffer.fromString(notebook.scheme), true, true)}`;
51
return notebook.with({ scheme: Schemas.vscodeNotebookCell, fragment });
52
}
53
54
export function parseMetadataUri(metadata: URI): URI | undefined {
55
if (metadata.scheme !== Schemas.vscodeNotebookMetadata) {
56
return undefined;
57
}
58
59
const _scheme = decodeBase64(metadata.fragment).toString();
60
61
return metadata.with({ scheme: _scheme, fragment: null });
62
}
63
64
export function generateMetadataUri(notebook: URI): URI {
65
const fragment = `${encodeBase64(VSBuffer.fromString(notebook.scheme), true, true)}`;
66
return notebook.with({ scheme: Schemas.vscodeNotebookMetadata, fragment });
67
}
68
69
export function extractCellOutputDetails(uri: URI): { notebook: URI; openIn: string; outputId?: string; cellFragment?: string; outputIndex?: number; cellHandle?: number; cellIndex?: number } | undefined {
70
if (uri.scheme !== Schemas.vscodeNotebookCellOutput) {
71
return;
72
}
73
74
const params = new URLSearchParams(uri.query);
75
const openIn = params.get('openIn');
76
if (!openIn) {
77
return;
78
}
79
const outputId = params.get('outputId') ?? undefined;
80
const parsedCell = parse(uri.with({ scheme: Schemas.vscodeNotebookCell, query: null }));
81
const outputIndex = params.get('outputIndex') ? parseInt(params.get('outputIndex') || '', 10) : undefined;
82
const notebookUri = parsedCell ? parsedCell.notebook : uri.with({
83
scheme: params.get('notebookScheme') || Schemas.file,
84
fragment: null,
85
query: null,
86
});
87
const cellIndex = params.get('cellIndex') ? parseInt(params.get('cellIndex') || '', 10) : undefined;
88
89
return {
90
notebook: notebookUri,
91
openIn: openIn,
92
outputId: outputId,
93
outputIndex: outputIndex,
94
cellHandle: parsedCell?.handle,
95
cellFragment: uri.fragment,
96
cellIndex: cellIndex,
97
};
98
}
99
100
101
export interface INotebookDocumentService {
102
readonly _serviceBrand: undefined;
103
104
getNotebook(uri: URI): INotebookDocument | undefined;
105
addNotebookDocument(document: INotebookDocument): void;
106
removeNotebookDocument(document: INotebookDocument): void;
107
}
108
109
export class NotebookDocumentWorkbenchService implements INotebookDocumentService {
110
declare readonly _serviceBrand: undefined;
111
112
private readonly _documents = new ResourceMap<INotebookDocument>();
113
114
getNotebook(uri: URI): INotebookDocument | undefined {
115
if (uri.scheme === Schemas.vscodeNotebookCell) {
116
const cellUri = parse(uri);
117
if (cellUri) {
118
const document = this._documents.get(cellUri.notebook);
119
if (document) {
120
return document;
121
}
122
}
123
}
124
if (uri.scheme === Schemas.vscodeNotebookCellOutput) {
125
const parsedData = extractCellOutputDetails(uri);
126
if (parsedData) {
127
const document = this._documents.get(parsedData.notebook);
128
if (document) {
129
return document;
130
}
131
}
132
}
133
134
return this._documents.get(uri);
135
}
136
137
addNotebookDocument(document: INotebookDocument) {
138
this._documents.set(document.uri, document);
139
}
140
141
removeNotebookDocument(document: INotebookDocument) {
142
this._documents.delete(document.uri);
143
}
144
145
}
146
147
registerSingleton(INotebookDocumentService, NotebookDocumentWorkbenchService, InstantiationType.Delayed);
148
149