New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
notebook image cleaning automation #159212
Changes from all commits
bc7c130
6d5a164
4f8342e
eef6539
93b73a5
5830c14
a19f9f3
1385f69
0d0cc73
6f892d0
69c9430
5296f31
83a4ee4
ca9ad19
635454b
146d685
742e98c
2261aac
9c441bd
727aa9c
9aa082b
09b615b
d08c452
05f532e
26d9a67
ba3752c
d84c229
dd8ee78
87ae4c2
ccfbb6d
d30095f
4f11fbb
d9d8e1a
095ed18
2ed743d
ea2add0
2e2bed9
ae3aeed
29f995a
fe00d03
24df26a
34369f4
8cd3b08
b106518
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ | ||
// Use IntelliSense to learn about possible attributes. | ||
// Hover to view descriptions of existing attributes. | ||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 | ||
"version": "0.2.0", | ||
"configurations": [ | ||
{ | ||
"args": [ | ||
"--extensionDevelopmentPath=${workspaceFolder}" | ||
], | ||
"name": "Launch Extension", | ||
"outFiles": [ | ||
"${workspaceFolder}/out/**/*.js" | ||
], | ||
"request": "launch", | ||
"type": "extensionHost" | ||
} | ||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,7 +9,7 @@ | |
"vscode": "^1.57.0" | ||
}, | ||
"enabledApiProposals": [ | ||
"documentPaste" | ||
"documentPaste" | ||
], | ||
"activationEvents": [ | ||
"*" | ||
|
@@ -27,21 +27,21 @@ | |
} | ||
}, | ||
"contributes": { | ||
"configuration":[ | ||
{ | ||
"properties": { | ||
"ipynb.experimental.pasteImages.enabled":{ | ||
"type": "boolean", | ||
"scope": "resource", | ||
"markdownDescription": "%ipynb.experimental.pasteImages.enabled%", | ||
"default": false, | ||
"tags": [ | ||
"experimental" | ||
] | ||
} | ||
} | ||
} | ||
], | ||
"configuration": [ | ||
{ | ||
"properties": { | ||
"ipynb.experimental.pasteImages.enabled": { | ||
"type": "boolean", | ||
"scope": "resource", | ||
"markdownDescription": "%ipynb.experimental.pasteImages.enabled%", | ||
"default": false, | ||
"tags": [ | ||
"experimental" | ||
] | ||
} | ||
} | ||
} | ||
], | ||
"commands": [ | ||
{ | ||
"command": "ipynb.newUntitledIpynb", | ||
|
@@ -52,6 +52,10 @@ | |
{ | ||
"command": "ipynb.openIpynbInNotebookEditor", | ||
"title": "Open ipynb file in notebook editor" | ||
}, | ||
{ | ||
"command": "ipynb.cleanInvalidImageAttachment", | ||
"title": "Clean invalid image attachment reference" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need the word "reference" here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm using |
||
} | ||
], | ||
"notebooks": [ | ||
|
@@ -66,16 +70,16 @@ | |
"priority": "default" | ||
} | ||
], | ||
"notebookRenderer": [ | ||
{ | ||
"id": "vscode.markdown-it-cell-attachment-renderer", | ||
"displayName": "Markdown it ipynb Cell Attachment renderer", | ||
"entrypoint": { | ||
"extends": "vscode.markdown-it-renderer", | ||
"path": "./notebook-out/cellAttachmentRenderer.js" | ||
} | ||
} | ||
], | ||
"notebookRenderer": [ | ||
{ | ||
"id": "vscode.markdown-it-cell-attachment-renderer", | ||
"displayName": "Markdown it ipynb Cell Attachment renderer", | ||
"entrypoint": { | ||
"extends": "vscode.markdown-it-renderer", | ||
"path": "./notebook-out/cellAttachmentRenderer.js" | ||
} | ||
} | ||
], | ||
"menus": { | ||
"file/newFile": [ | ||
{ | ||
|
@@ -90,6 +94,10 @@ | |
{ | ||
"command": "ipynb.openIpynbInNotebookEditor", | ||
"when": "false" | ||
}, | ||
{ | ||
"command": "ipynb.cleanInvalidImageAttachment", | ||
"when": "false" | ||
} | ||
] | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
/*--------------------------------------------------------------------------------------------- | ||
* Copyright (c) Microsoft Corporation. All rights reserved. | ||
* Licensed under the MIT License. See License.txt in the project root for license information. | ||
*--------------------------------------------------------------------------------------------*/ | ||
|
||
export function deepClone<T>(obj: T): T { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we don't have more generally available versions of these functions? (and better tested?) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @amunger currently we don't, I borrowed this from the core. |
||
if (!obj || typeof obj !== 'object') { | ||
return obj; | ||
} | ||
if (obj instanceof RegExp) { | ||
// See https://github.com/microsoft/TypeScript/issues/10990 | ||
return obj as any; | ||
} | ||
const result: any = Array.isArray(obj) ? [] : {}; | ||
Object.keys(<any>obj).forEach((key: string) => { | ||
if ((<any>obj)[key] && typeof (<any>obj)[key] === 'object') { | ||
result[key] = deepClone((<any>obj)[key]); | ||
} else { | ||
result[key] = (<any>obj)[key]; | ||
} | ||
}); | ||
return result; | ||
} | ||
|
||
// from https://github.com/microsoft/vscode/blob/43ae27a30e7b5e8711bf6b218ee39872ed2b8ef6/src/vs/base/common/objects.ts#L117 | ||
export function objectEquals(one: any, other: any) { | ||
if (one === other) { | ||
return true; | ||
} | ||
if (one === null || one === undefined || other === null || other === undefined) { | ||
return false; | ||
} | ||
if (typeof one !== typeof other) { | ||
return false; | ||
} | ||
if (typeof one !== 'object') { | ||
return false; | ||
} | ||
if ((Array.isArray(one)) !== (Array.isArray(other))) { | ||
return false; | ||
} | ||
|
||
let i: number; | ||
let key: string; | ||
|
||
if (Array.isArray(one)) { | ||
if (one.length !== other.length) { | ||
return false; | ||
} | ||
for (i = 0; i < one.length; i++) { | ||
if (!objectEquals(one[i], other[i])) { | ||
return false; | ||
} | ||
} | ||
} else { | ||
const oneKeys: string[] = []; | ||
|
||
for (key in one) { | ||
oneKeys.push(key); | ||
} | ||
oneKeys.sort(); | ||
const otherKeys: string[] = []; | ||
for (key in other) { | ||
otherKeys.push(key); | ||
} | ||
otherKeys.sort(); | ||
if (!objectEquals(oneKeys, otherKeys)) { | ||
return false; | ||
} | ||
for (i = 0; i < oneKeys.length; i++) { | ||
if (!objectEquals(one[oneKeys[i]], other[oneKeys[i]])) { | ||
return false; | ||
} | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
|
||
interface Options<T> { | ||
callback: (value: T) => void; | ||
|
||
merge?: (input: T[]) => T; | ||
delay?: number; | ||
} | ||
|
||
|
||
export class DebounceTrigger<T> { | ||
|
||
private _isPaused = 0; | ||
protected _queue: T[] = []; | ||
private _callbackFn: (value: T) => void; | ||
private _mergeFn?: (input: T[]) => T; | ||
private readonly _delay: number; | ||
private _handle: any | undefined; | ||
|
||
constructor(options: Options<T>) { | ||
this._callbackFn = options.callback; | ||
this._mergeFn = options.merge; | ||
this._delay = options.delay ?? 100; | ||
} | ||
|
||
private pause(): void { | ||
this._isPaused++; | ||
} | ||
|
||
private resume(): void { | ||
if (this._isPaused !== 0 && --this._isPaused === 0) { | ||
if (this._mergeFn) { | ||
const items = Array.from(this._queue); | ||
this._queue = []; | ||
this._callbackFn(this._mergeFn(items)); | ||
|
||
} else { | ||
while (!this._isPaused && this._queue.length !== 0) { | ||
this._callbackFn(this._queue.shift()!); | ||
} | ||
} | ||
} | ||
} | ||
|
||
trigger(item: T): void { | ||
if (!this._handle) { | ||
this.pause(); | ||
this._handle = setTimeout(() => { | ||
this._handle = undefined; | ||
this.resume(); | ||
}, this._delay); | ||
} | ||
|
||
if (this._isPaused !== 0) { | ||
this._queue.push(item); | ||
} else { | ||
this._callbackFn(item); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
space to tab