Merge branch 'rebornix/stream-output'
commit
cc58f84bfe
|
@ -211,7 +211,7 @@ class RichRenderer implements IOutputTransformContribution {
|
|||
renderPlainText(output: IDisplayOutputViewModel, notebookUri: URI, container: HTMLElement): IRenderOutput {
|
||||
const data = output.model.data['text/plain'];
|
||||
const contentNode = DOM.$('.output-plaintext');
|
||||
truncatedArrayOfString(contentNode, isArray(data) ? data : [data], this.openerService, this.textFileService, this.themeService, true);
|
||||
truncatedArrayOfString(contentNode, isArray(data) ? data : [data], this.openerService, this.textFileService, this.themeService);
|
||||
container.appendChild(contentNode);
|
||||
|
||||
return { type: RenderOutputType.None, hasDynamicHeight: false };
|
||||
|
|
|
@ -23,8 +23,8 @@ class StreamRenderer implements IOutputTransformContribution {
|
|||
|
||||
render(viewModel: IStreamOutputViewModel, container: HTMLElement): IRenderOutput {
|
||||
const output = viewModel.model;
|
||||
const contentNode = DOM.$('.output-stream');
|
||||
truncatedArrayOfString(contentNode, [output.text], this.openerService, this.textFileService, this.themeService, false);
|
||||
const contentNode = DOM.$('span.output-stream');
|
||||
truncatedArrayOfString(contentNode, [output.text], this.openerService, this.textFileService, this.themeService);
|
||||
container.appendChild(contentNode);
|
||||
return { type: RenderOutputType.None, hasDynamicHeight: false };
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ function generateViewMoreElement(outputs: string[], openerService: IOpenerServic
|
|||
return element;
|
||||
}
|
||||
|
||||
export function truncatedArrayOfString(container: HTMLElement, outputs: string[], openerService: IOpenerService, textFileService: ITextFileService, themeService: IThemeService, renderANSI: boolean) {
|
||||
export function truncatedArrayOfString(container: HTMLElement, outputs: string[], openerService: IOpenerService, textFileService: ITextFileService, themeService: IThemeService) {
|
||||
const fullLen = outputs.reduce((p, c) => {
|
||||
return p + c.length;
|
||||
}, 0);
|
||||
|
@ -65,14 +65,7 @@ export function truncatedArrayOfString(container: HTMLElement, outputs: string[]
|
|||
const sizeBufferLimitPosition = buffer.getPositionAt(SIZE_LIMIT);
|
||||
if (sizeBufferLimitPosition.lineNumber < LINES_LIMIT) {
|
||||
const truncatedText = buffer.getValueInRange(new Range(1, 1, sizeBufferLimitPosition.lineNumber, sizeBufferLimitPosition.column), EndOfLinePreference.TextDefined);
|
||||
if (renderANSI) {
|
||||
container.appendChild(handleANSIOutput(truncatedText, themeService));
|
||||
} else {
|
||||
const pre = DOM.$('pre');
|
||||
pre.innerText = truncatedText;
|
||||
container.appendChild(pre);
|
||||
}
|
||||
|
||||
container.appendChild(handleANSIOutput(truncatedText, themeService));
|
||||
// view more ...
|
||||
container.appendChild(generateViewMoreElement(outputs, openerService, textFileService));
|
||||
return;
|
||||
|
@ -89,42 +82,19 @@ export function truncatedArrayOfString(container: HTMLElement, outputs: string[]
|
|||
if (buffer.getLineCount() < LINES_LIMIT) {
|
||||
const lineCount = buffer.getLineCount();
|
||||
const fullRange = new Range(1, 1, lineCount, Math.max(1, buffer.getLineLastNonWhitespaceColumn(lineCount)));
|
||||
|
||||
if (renderANSI) {
|
||||
const pre = DOM.$('pre');
|
||||
container.appendChild(pre);
|
||||
|
||||
pre.appendChild(handleANSIOutput(buffer.getValueInRange(fullRange, EndOfLinePreference.TextDefined), themeService));
|
||||
} else {
|
||||
const pre = DOM.$('pre');
|
||||
container.appendChild(pre);
|
||||
pre.innerText = buffer.getValueInRange(fullRange, EndOfLinePreference.TextDefined);
|
||||
}
|
||||
container.appendChild(handleANSIOutput(buffer.getValueInRange(fullRange, EndOfLinePreference.TextDefined), themeService));
|
||||
return;
|
||||
}
|
||||
|
||||
if (renderANSI) {
|
||||
const pre = DOM.$('pre');
|
||||
container.appendChild(pre);
|
||||
pre.appendChild(handleANSIOutput(buffer.getValueInRange(new Range(1, 1, LINES_LIMIT - 5, buffer.getLineLastNonWhitespaceColumn(LINES_LIMIT - 5)), EndOfLinePreference.TextDefined), themeService));
|
||||
} else {
|
||||
const pre = DOM.$('pre');
|
||||
pre.innerText = buffer.getValueInRange(new Range(1, 1, LINES_LIMIT - 5, buffer.getLineLastNonWhitespaceColumn(LINES_LIMIT - 5)), EndOfLinePreference.TextDefined);
|
||||
container.appendChild(pre);
|
||||
}
|
||||
|
||||
const pre = DOM.$('pre');
|
||||
container.appendChild(pre);
|
||||
pre.appendChild(handleANSIOutput(buffer.getValueInRange(new Range(1, 1, LINES_LIMIT - 5, buffer.getLineLastNonWhitespaceColumn(LINES_LIMIT - 5)), EndOfLinePreference.TextDefined), themeService));
|
||||
|
||||
// view more ...
|
||||
container.appendChild(generateViewMoreElement(outputs, openerService, textFileService));
|
||||
|
||||
const lineCount = buffer.getLineCount();
|
||||
if (renderANSI) {
|
||||
const pre = DOM.$('div');
|
||||
container.appendChild(pre);
|
||||
pre.appendChild(handleANSIOutput(buffer.getValueInRange(new Range(lineCount - 5, 1, lineCount, buffer.getLineLastNonWhitespaceColumn(lineCount)), EndOfLinePreference.TextDefined), themeService));
|
||||
} else {
|
||||
const post = DOM.$('div');
|
||||
post.innerText = buffer.getValueInRange(new Range(lineCount - 5, 1, lineCount, buffer.getLineLastNonWhitespaceColumn(lineCount)), EndOfLinePreference.TextDefined);
|
||||
container.appendChild(post);
|
||||
}
|
||||
const pre2 = DOM.$('div');
|
||||
container.appendChild(pre2);
|
||||
pre2.appendChild(handleANSIOutput(buffer.getValueInRange(new Range(lineCount - 5, 1, lineCount, buffer.getLineLastNonWhitespaceColumn(lineCount)), EndOfLinePreference.TextDefined), themeService));
|
||||
}
|
||||
|
|
|
@ -36,6 +36,16 @@ export class OutputElement extends Disposable {
|
|||
domNode!: HTMLElement;
|
||||
renderResult?: IRenderOutput;
|
||||
|
||||
public useDedicatedDOM: boolean = true;
|
||||
|
||||
get domClientHeight() {
|
||||
if (this.useDedicatedDOM) {
|
||||
return this.domNode.clientHeight;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
constructor(
|
||||
private notebookEditor: INotebookEditor,
|
||||
private notebookService: INotebookService,
|
||||
|
@ -47,6 +57,17 @@ export class OutputElement extends Disposable {
|
|||
super();
|
||||
}
|
||||
|
||||
detach() {
|
||||
this.domNode.parentElement?.removeChild(this.domNode);
|
||||
}
|
||||
|
||||
updateDOMTop(top: number) {
|
||||
if (this.useDedicatedDOM) {
|
||||
this.domNode.style.top = `${top}px`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
render(index: number, beforeElement?: HTMLElement) {
|
||||
if (this.viewCell.metadata.outputCollapsed) {
|
||||
return;
|
||||
|
@ -58,10 +79,11 @@ export class OutputElement extends Disposable {
|
|||
|
||||
const notebookTextModel = this.notebookEditor.viewModel.notebookDocument;
|
||||
|
||||
const outputItemDiv = document.createElement('div');
|
||||
let outputItemDiv;
|
||||
let result: IRenderOutput | undefined = undefined;
|
||||
|
||||
if (this.output.isDisplayOutput()) {
|
||||
outputItemDiv = document.createElement('div');
|
||||
const [mimeTypes, pick] = this.output.resolveMimeTypes(notebookTextModel);
|
||||
if (mimeTypes.length > 1) {
|
||||
outputItemDiv.style.position = 'relative';
|
||||
|
@ -106,8 +128,27 @@ export class OutputElement extends Disposable {
|
|||
|
||||
this.output.pickedMimeType = pick;
|
||||
}
|
||||
} else if (this.output.isStreamOutput()) {
|
||||
if (!beforeElement && this.outputContainer.lastChild && (<HTMLElement>this.outputContainer.lastChild).classList.contains('stream-output') && this.output.isStreamOutput()) {
|
||||
this.useDedicatedDOM = false;
|
||||
// the previous output and this one are both stream output
|
||||
outputItemDiv = this.outputContainer.lastChild as HTMLElement;
|
||||
const innerContainer = outputItemDiv.lastChild && (<HTMLElement>outputItemDiv.lastChild).classList.contains('output-inner-container') ? outputItemDiv.lastChild as HTMLElement : document.createElement('div');
|
||||
outputItemDiv.classList.add('stream-output');
|
||||
DOM.append(outputItemDiv, innerContainer);
|
||||
|
||||
result = this.notebookEditor.getOutputRenderer().render(this.output, innerContainer, undefined, this.getNotebookUri(),);
|
||||
} else {
|
||||
outputItemDiv = document.createElement('div');
|
||||
const innerContainer = DOM.$('.output-inner-container');
|
||||
outputItemDiv.classList.add('stream-output');
|
||||
DOM.append(outputItemDiv, innerContainer);
|
||||
|
||||
result = this.notebookEditor.getOutputRenderer().render(this.output, innerContainer, undefined, this.getNotebookUri(),);
|
||||
}
|
||||
} else {
|
||||
// for text and error, there is no mimetype
|
||||
outputItemDiv = document.createElement('div');
|
||||
const innerContainer = DOM.$('.output-inner-container');
|
||||
DOM.append(outputItemDiv, innerContainer);
|
||||
|
||||
|
@ -124,7 +165,7 @@ export class OutputElement extends Disposable {
|
|||
|
||||
if (beforeElement) {
|
||||
this.outputContainer.insertBefore(outputItemDiv, beforeElement);
|
||||
} else {
|
||||
} else if (this.useDedicatedDOM) {
|
||||
this.outputContainer.appendChild(outputItemDiv);
|
||||
}
|
||||
|
||||
|
@ -165,11 +206,13 @@ export class OutputElement extends Disposable {
|
|||
this.resizeListener.add(elementSizeObserver);
|
||||
this.viewCell.updateOutputHeight(index, clientHeight);
|
||||
} else if (result.type === RenderOutputType.None) { // no-op if it's a webview
|
||||
const clientHeight = Math.ceil(outputItemDiv.clientHeight);
|
||||
this.viewCell.updateOutputHeight(index, clientHeight);
|
||||
if (this.useDedicatedDOM) {
|
||||
const clientHeight = Math.ceil(outputItemDiv.clientHeight);
|
||||
this.viewCell.updateOutputHeight(index, clientHeight);
|
||||
|
||||
const top = this.viewCell.getOutputOffsetInContainer(index);
|
||||
outputItemDiv.style.top = `${top}px`;
|
||||
const top = this.viewCell.getOutputOffsetInContainer(index);
|
||||
outputItemDiv.style.top = `${top}px`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -268,7 +311,7 @@ export class OutputContainer extends Disposable {
|
|||
const index = viewCell.outputsViewModels.indexOf(key);
|
||||
if (index >= 0) {
|
||||
const top = this.viewCell.getOutputOffsetInContainer(index);
|
||||
value.domNode.style.top = `${top}px`;
|
||||
value.updateDOMTop(top);
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
@ -330,8 +373,7 @@ export class OutputContainer extends Disposable {
|
|||
if (renderedOutput.renderResult.type !== RenderOutputType.None) {
|
||||
this.notebookEditor.createInset(this.viewCell, renderedOutput.renderResult as IInsetRenderOutput, this.viewCell.getOutputOffset(index));
|
||||
} else {
|
||||
// Anything else, just update the height
|
||||
this.viewCell.updateOutputHeight(index, renderedOutput.domNode.clientHeight);
|
||||
this.viewCell.updateOutputHeight(index, renderedOutput.domClientHeight);
|
||||
}
|
||||
} else {
|
||||
// Wasn't previously rendered, render it now
|
||||
|
@ -352,7 +394,7 @@ export class OutputContainer extends Disposable {
|
|||
this.viewCell.outputsViewModels.forEach((o, i) => {
|
||||
const renderedOutput = this.outputEntries.get(o);
|
||||
if (renderedOutput && renderedOutput.renderResult && renderedOutput.renderResult.type === RenderOutputType.None && !renderedOutput.renderResult.hasDynamicHeight) {
|
||||
this.viewCell.updateOutputHeight(i, renderedOutput.domNode.clientHeight);
|
||||
this.viewCell.updateOutputHeight(i, renderedOutput.domClientHeight);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -420,7 +462,7 @@ export class OutputContainer extends Disposable {
|
|||
// already removed
|
||||
removedKeys.push(key);
|
||||
// remove element from DOM
|
||||
this.templateData?.outputContainer?.removeChild(value.domNode);
|
||||
value.detach();
|
||||
if (key.isDisplayOutput()) {
|
||||
this.notebookEditor.removeInset(key);
|
||||
}
|
||||
|
|
|
@ -122,6 +122,12 @@ export class CodeCell extends Disposable {
|
|||
}
|
||||
}));
|
||||
|
||||
this._register(viewCell.onDidChangeLayout((e) => {
|
||||
if (e.totalHeight) {
|
||||
this.relayoutCell();
|
||||
}
|
||||
}));
|
||||
|
||||
this._register(templateData.editor.onDidContentSizeChange((e) => {
|
||||
if (e.contentHeightChanged) {
|
||||
if (this.viewCell.layoutInfo.editorHeight !== e.contentHeight) {
|
||||
|
|
Loading…
Reference in New Issue