Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/contrib/notebook/common/model/notebookMetadataTextModel.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 { toFormattedString } from '../../../../../base/common/jsonFormatter.js';
7
import { INotebookDocumentMetadataTextModel, INotebookTextModel, NotebookCellMetadata, NotebookCellsChangeType, NotebookDocumentMetadata, NotebookMetadataUri, TransientDocumentMetadata } from '../notebookCommon.js';
8
import { StringSHA1 } from '../../../../../base/common/hash.js';
9
import { Disposable } from '../../../../../base/common/lifecycle.js';
10
import { URI } from '../../../../../base/common/uri.js';
11
import { DefaultEndOfLine, EndOfLinePreference, ITextBuffer } from '../../../../../editor/common/model.js';
12
import { Emitter } from '../../../../../base/common/event.js';
13
import { Range } from '../../../../../editor/common/core/range.js';
14
import { createTextBuffer } from '../../../../../editor/common/model/textModel.js';
15
16
export function getFormattedNotebookMetadataJSON(transientMetadata: TransientDocumentMetadata | undefined, metadata: NotebookDocumentMetadata) {
17
let filteredMetadata: { [key: string]: any } = {};
18
19
if (transientMetadata) {
20
const keys = new Set([...Object.keys(metadata)]);
21
for (const key of keys) {
22
if (!(transientMetadata[key as keyof NotebookCellMetadata])
23
) {
24
filteredMetadata[key] = metadata[key as keyof NotebookCellMetadata];
25
}
26
}
27
} else {
28
filteredMetadata = metadata;
29
}
30
31
const metadataSource = toFormattedString(filteredMetadata, {});
32
33
return metadataSource;
34
}
35
36
export class NotebookDocumentMetadataTextModel extends Disposable implements INotebookDocumentMetadataTextModel {
37
public readonly uri: URI;
38
public get metadata(): NotebookDocumentMetadata {
39
return this.notebookModel.metadata;
40
}
41
private readonly _onDidChange = this._register(new Emitter<void>());
42
public readonly onDidChange = this._onDidChange.event;
43
44
private _textBufferHash: string | null = null;
45
private _textBuffer?: ITextBuffer;
46
get textBuffer() {
47
if (this._textBuffer) {
48
return this._textBuffer;
49
}
50
51
const source = getFormattedNotebookMetadataJSON(this.notebookModel.transientOptions.transientDocumentMetadata, this.metadata);
52
this._textBuffer = this._register(createTextBuffer(source, DefaultEndOfLine.LF).textBuffer);
53
54
this._register(this._textBuffer.onDidChangeContent(() => {
55
this._onDidChange.fire();
56
}));
57
58
return this._textBuffer;
59
}
60
61
constructor(public readonly notebookModel: INotebookTextModel) {
62
super();
63
this.uri = NotebookMetadataUri.generate(this.notebookModel.uri);
64
this._register(this.notebookModel.onDidChangeContent((e) => {
65
if (e.rawEvents.some(event => event.kind === NotebookCellsChangeType.ChangeDocumentMetadata || event.kind === NotebookCellsChangeType.ModelChange)) {
66
this._textBuffer?.dispose();
67
this._textBuffer = undefined;
68
this._textBufferHash = null;
69
this._onDidChange.fire();
70
}
71
}));
72
}
73
74
getHash() {
75
if (this._textBufferHash !== null) {
76
return this._textBufferHash;
77
}
78
79
const shaComputer = new StringSHA1();
80
const snapshot = this.textBuffer.createSnapshot(false);
81
let text: string | null;
82
while ((text = snapshot.read())) {
83
shaComputer.update(text);
84
}
85
this._textBufferHash = shaComputer.digest();
86
return this._textBufferHash;
87
}
88
89
public getValue() {
90
const fullRange = this.getFullModelRange();
91
const eol = this.textBuffer.getEOL();
92
if (eol === '\n') {
93
return this.textBuffer.getValueInRange(fullRange, EndOfLinePreference.LF);
94
} else {
95
return this.textBuffer.getValueInRange(fullRange, EndOfLinePreference.CRLF);
96
}
97
}
98
private getFullModelRange() {
99
const lineCount = this.textBuffer.getLineCount();
100
return new Range(1, 1, lineCount, this.textBuffer.getLineLength(lineCount) + 1);
101
}
102
103
}
104
105