Optimize indentation detection

This commit is contained in:
Don Jayamanne 2021-08-17 14:51:53 -07:00
parent 0882f1e571
commit 09f68d545d
3 changed files with 42 additions and 4 deletions

View file

@ -64,8 +64,7 @@
"watch": "npx gulp watch-extension:ipynb"
},
"dependencies": {
"@enonic/fnv-plus": "^1.3.0",
"detect-indent": "^6.0.0"
"@enonic/fnv-plus": "^1.3.0"
},
"devDependencies": {
"@jupyterlab/coreutils": "^3.1.0"

View file

@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/
import type { nbformat } from '@jupyterlab/coreutils';
import * as detectIndent from 'detect-indent';
import * as vscode from 'vscode';
import { defaultNotebookFormat } from './constants';
import { getPreferredLanguage, jupyterNotebookModelToNotebookData } from './deserializers';
@ -41,7 +40,7 @@ export class NotebookSerializer implements vscode.NotebookSerializer {
}
// Then compute indent from the contents
const indentAmount = contents ? detectIndent(contents).indent : ' ';
const indentAmount = contents ? detectIndent(contents) : ' ';
const preferredCellLanguage = getPreferredLanguage(json.metadata);
// Ensure we always have a blank cell.
@ -94,3 +93,17 @@ export class NotebookSerializer implements vscode.NotebookSerializer {
return JSON.stringify(notebookContent, undefined, indentAmount);
}
}
export function detectIndent(jsonString: string) {
// ipynb is a JSON string of Object, hence first character will always `{`.
// Lets just take the distance between the first `{` and the next non-white space character`, ignoring \r & \n
if (!jsonString.startsWith('{')) {
return '';
}
// We're only interested in a small part of the string.
// The assumption is that we won't have an indentation of 10, just around 5 or so.
jsonString = jsonString.substring(1, 10).replace(/\r?\n/g, '');
// first index of non white space is the indentation.
const firstPositionOfNonWhiteSpace = jsonString.length - jsonString.trimStart().length;
return jsonString.substring(0, firstPositionOfNonWhiteSpace);
}

View file

@ -7,6 +7,7 @@ import { nbformat } from '@jupyterlab/coreutils';
import * as assert from 'assert';
import * as vscode from 'vscode';
import { jupyterCellOutputToCellOutput, jupyterNotebookModelToNotebookData } from '../deserializers';
import { detectIndent } from '../notebookSerializer';
function deepStripProperties(obj: any, props: string[]) {
for (let prop in obj) {
@ -53,6 +54,31 @@ suite('ipynb serializer', () => {
assert.deepStrictEqual(notebook.cells, [expectedCodeCell, expectedMarkdownCell]);
});
suite('Indentation detection', () => {
const ipynbNotebook: nbformat.INotebookContent = {
cells: [{ cell_type: 'raw', metadata: {}, source: [] }],
metadata: {
orig_nbformat: 4
},
nbformat: 4,
nbformat_minor: 0
};
test('JSON with no indents', () => {
assert.deepStrictEqual(detectIndent(JSON.stringify(ipynbNotebook, undefined, '')), '');
});
test('JSON with 1 indent', () => {
assert.deepStrictEqual(detectIndent(JSON.stringify(ipynbNotebook, undefined, ' ')), ' ');
});
test('JSON with 4 indent', () => {
assert.deepStrictEqual(detectIndent(JSON.stringify(ipynbNotebook, undefined, ' ')), ' ');
});
test('JSON with 1 tab indent', () => {
assert.deepStrictEqual(detectIndent(JSON.stringify(ipynbNotebook, undefined, ' ')), ' ');
});
test('JSON with 3 tab indent', () => {
assert.deepStrictEqual(detectIndent(JSON.stringify(ipynbNotebook, undefined, ' ')), ' ');
});
});
suite('Outputs', () => {
function validateCellOutputTranslation(
outputs: nbformat.IOutput[],