Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
3e2c2fe5
V
vscode
项目概览
xxadev
/
vscode
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
3e2c2fe5
编写于
12月 17, 2019
作者:
P
Peng Lyu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
reusable webview
上级
8137a92d
变更
12
隐藏空白更改
内联
并排
Showing
12 changed file
with
290 addition
and
88 deletion
+290
-88
src/vs/base/browser/ui/list/listView.ts
src/vs/base/browser/ui/list/listView.ts
+7
-0
src/vs/base/browser/ui/list/listWidget.ts
src/vs/base/browser/ui/list/listWidget.ts
+5
-0
src/vs/base/browser/ui/scrollbar/scrollableElement.ts
src/vs/base/browser/ui/scrollbar/scrollableElement.ts
+4
-0
src/vs/workbench/contrib/notebook/browser/cellRenderer.ts
src/vs/workbench/contrib/notebook/browser/cellRenderer.ts
+5
-1
src/vs/workbench/contrib/notebook/browser/contentWidget.ts
src/vs/workbench/contrib/notebook/browser/contentWidget.ts
+111
-0
src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts
...rkbench/contrib/notebook/browser/notebook.contribution.ts
+1
-3
src/vs/workbench/contrib/notebook/browser/notebookEditor.ts
src/vs/workbench/contrib/notebook/browser/notebookEditor.ts
+55
-80
src/vs/workbench/contrib/notebook/browser/outputRenderer.ts
src/vs/workbench/contrib/notebook/browser/outputRenderer.ts
+0
-2
src/vs/workbench/contrib/webview/browser/baseWebviewElement.ts
...s/workbench/contrib/webview/browser/baseWebviewElement.ts
+56
-1
src/vs/workbench/contrib/webview/browser/dynamicWebviewEditorOverlay.ts
...ch/contrib/webview/browser/dynamicWebviewEditorOverlay.ts
+5
-0
src/vs/workbench/contrib/webview/browser/pre/main.js
src/vs/workbench/contrib/webview/browser/pre/main.js
+38
-1
src/vs/workbench/contrib/webview/browser/webview.ts
src/vs/workbench/contrib/webview/browser/webview.ts
+3
-0
未找到文件。
src/vs/base/browser/ui/list/listView.ts
浏览文件 @
3e2c2fe5
...
...
@@ -21,6 +21,7 @@ import { equals, distinct } from 'vs/base/common/arrays';
import
{
DataTransfers
,
StaticDND
,
IDragAndDropData
}
from
'
vs/base/browser/dnd
'
;
import
{
disposableTimeout
,
Delayer
}
from
'
vs/base/common/async
'
;
import
{
isFirefox
}
from
'
vs/base/browser/browser
'
;
import
{
IMouseWheelEvent
}
from
'
vs/base/browser/mouseEvent
'
;
interface
IItem
<
T
>
{
readonly
id
:
string
;
...
...
@@ -268,6 +269,10 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
this
.
layout
();
}
public
triggerScrollFromMouseWheelEvent
(
browserEvent
:
IMouseWheelEvent
)
{
this
.
scrollableElement
.
triggerScrollFromMouseWheelEvent
(
browserEvent
);
}
updateDynamicHeight
(
index
:
number
,
element
:
T
,
size
:
number
):
void
{
this
.
rangeMap
.
splice
(
index
,
1
,
[
{
...
...
@@ -283,6 +288,8 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
this
.
updateItemInDOM
(
this
.
items
[
i
],
i
);
}
}
this
.
_onDidChangeContentHeight
.
fire
(
this
.
contentHeight
);
}
splice
(
start
:
number
,
deleteCount
:
number
,
elements
:
T
[]
=
[]):
T
[]
{
...
...
src/vs/base/browser/ui/list/listWidget.ts
浏览文件 @
3e2c2fe5
...
...
@@ -26,6 +26,7 @@ import { CombinedSpliceable } from 'vs/base/browser/ui/list/splice';
import
{
clamp
}
from
'
vs/base/common/numbers
'
;
import
{
matchesPrefix
}
from
'
vs/base/common/filters
'
;
import
{
IDragAndDropData
}
from
'
vs/base/browser/dnd
'
;
import
{
IMouseWheelEvent
}
from
'
vs/base/browser/mouseEvent
'
;
interface
ITraitChangeEvent
{
indexes
:
number
[];
...
...
@@ -1305,6 +1306,10 @@ export class List<T> implements ISpliceable<T>, IDisposable {
this
.
eventBufferer
.
bufferEvents
(()
=>
this
.
spliceable
.
splice
(
start
,
deleteCount
,
elements
));
}
public
triggerScrollFromMouseWheelEvent
(
browserEvent
:
IMouseWheelEvent
)
{
this
.
view
.
triggerScrollFromMouseWheelEvent
(
browserEvent
);
}
updateDynamicHeight
(
index
:
number
,
element
:
T
,
size
:
number
):
void
{
this
.
view
.
updateDynamicHeight
(
index
,
element
,
size
);
}
...
...
src/vs/base/browser/ui/scrollbar/scrollableElement.ts
浏览文件 @
3e2c2fe5
...
...
@@ -298,6 +298,10 @@ export abstract class AbstractScrollableElement extends Widget {
this
.
_revealOnScroll
=
value
;
}
public
triggerScrollFromMouseWheelEvent
(
browserEvent
:
IMouseWheelEvent
)
{
this
.
_onMouseWheel
(
new
StandardWheelEvent
(
browserEvent
));
}
// -------------------- mouse wheel scrolling --------------------
private
_setListeningToMouseWheel
(
shouldListen
:
boolean
):
void
{
...
...
src/vs/workbench/contrib/notebook/browser/cellRenderer.ts
浏览文件 @
3e2c2fe5
...
...
@@ -32,13 +32,13 @@ import { ITextModel } from 'vs/editor/common/model';
import
{
IModeService
}
from
'
vs/editor/common/services/modeService
'
;
import
{
Emitter
}
from
'
vs/base/common/event
'
;
import
{
IWebviewService
}
from
'
vs/workbench/contrib/webview/browser/webview
'
;
import
{
IMouseWheelEvent
}
from
'
vs/base/browser/mouseEvent
'
;
export
class
ViewCell
{
private
_textModel
:
ITextModel
|
null
=
null
;
private
_mdRenderer
:
marked
.
Renderer
|
null
=
null
;
private
_html
:
string
|
null
=
null
;
private
_dynamicHeight
:
number
|
null
=
null
;
private
_output
:
HTMLElement
|
null
=
null
;
protected
readonly
_onDidDispose
=
new
Emitter
<
void
>
();
readonly
onDidDispose
=
this
.
_onDidDispose
.
event
;
...
...
@@ -171,6 +171,8 @@ export interface NotebookHandler {
saveNotebookCell
(
cell
:
ViewCell
):
void
;
layoutElement
(
cell
:
ViewCell
,
height
:
number
):
void
;
createContentWidget
(
cell
:
ViewCell
,
shadowContent
:
string
,
shadowElement
:
HTMLElement
,
offset
:
number
):
void
;
disposeViewCell
(
cell
:
ViewCell
):
void
;
triggerWheel
(
event
:
IMouseWheelEvent
):
void
;
}
export
interface
CellRenderTemplate
{
...
...
@@ -618,6 +620,8 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
this
.
disposables
.
delete
(
templateData
.
outputContainer
!
);
}
}
this
.
handler
.
disposeViewCell
(
element
);
}
getSimpleCodeEditorWidgetOptions
():
ICodeEditorWidgetOptions
{
...
...
src/vs/workbench/contrib/notebook/browser/contentWidget.ts
0 → 100644
浏览文件 @
3e2c2fe5
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
{
NotebookHandler
,
ViewCell
}
from
'
vs/workbench/contrib/notebook/browser/cellRenderer
'
;
import
{
IWebviewService
,
WebviewElement
}
from
'
vs/workbench/contrib/webview/browser/webview
'
;
import
*
as
DOM
from
'
vs/base/browser/dom
'
;
import
*
as
UUID
from
'
vs/base/common/uuid
'
;
import
{
Disposable
,
DisposableStore
}
from
'
vs/base/common/lifecycle
'
;
export
class
WebviewContentWidget
extends
Disposable
{
public
element
:
HTMLElement
;
public
webview
:
WebviewElement
;
private
_dimension
:
DOM
.
Dimension
|
null
=
null
;
private
readonly
_localStore
=
new
DisposableStore
();
private
_detachedFromViewEvents
:
boolean
=
false
;
get
detachedFromViewEvents
()
{
return
this
.
_detachedFromViewEvents
;
}
set
detachedFromViewEvents
(
newState
:
boolean
)
{
this
.
_detachedFromViewEvents
=
newState
;
this
.
_localStore
.
clear
();
}
constructor
(
public
shadowElement
:
HTMLElement
,
public
cell
:
ViewCell
,
public
offset
:
number
,
public
webviewService
:
IWebviewService
,
shadowContent
:
string
,
public
notebookHandler
:
NotebookHandler
)
{
super
();
this
.
element
=
document
.
createElement
(
'
div
'
);
this
.
element
.
style
.
width
=
'
calc(100% - 36px)
'
;
this
.
element
.
style
.
height
=
'
700px
'
;
this
.
element
.
style
.
position
=
'
absolute
'
;
this
.
element
.
style
.
margin
=
'
0px 24px 0px 24px
'
;
this
.
webview
=
this
.
_createInset
(
webviewService
,
shadowContent
);
this
.
webview
.
mountTo
(
this
.
element
);
this
.
_localStore
.
add
(
this
.
webview
.
onDidSetInitialDimension
(
dimension
=>
{
this
.
_dimension
=
dimension
;
this
.
shadowElement
.
style
.
height
=
`
${
dimension
.
height
}
px`
;
this
.
shadowElement
.
style
.
maxWidth
=
'
100%
'
;
this
.
shadowElement
.
style
.
maxHeight
=
'
700px
'
;
this
.
element
.
style
.
height
=
`
${
dimension
.
height
}
px`
;
this
.
element
.
style
.
maxWidth
=
'
100%
'
;
this
.
element
.
style
.
maxHeight
=
'
700px
'
;
const
lineNum
=
cell
.
lineCount
;
const
totalHeight
=
Math
.
max
(
lineNum
+
1
,
5
)
*
21
;
cell
.
setDynamicHeight
(
totalHeight
+
32
+
dimension
.
height
);
notebookHandler
.
layoutElement
(
cell
,
totalHeight
+
32
+
dimension
.
height
);
}));
this
.
_localStore
.
add
(
this
.
webview
.
onDidWheel
(
e
=>
{
this
.
notebookHandler
.
triggerWheel
(
e
);
}));
}
updateInitialization
(
shadowElement
:
HTMLElement
,
cell
:
ViewCell
,
offset
:
number
,
shadowContent
:
string
)
{
this
.
_localStore
.
clear
();
this
.
shadowElement
=
shadowElement
;
this
.
cell
=
cell
;
this
.
offset
=
offset
;
this
.
element
.
style
.
height
=
'
700px
'
;
this
.
element
.
style
.
width
=
'
calc(100% - 36px)
'
;
this
.
webview
.
html
=
shadowContent
;
this
.
_localStore
.
add
(
this
.
webview
.
onDidSetInitialDimension
(
dimension
=>
{
this
.
_dimension
=
dimension
;
this
.
shadowElement
.
style
.
height
=
`
${
dimension
.
height
}
px`
;
this
.
shadowElement
.
style
.
maxWidth
=
'
100%
'
;
this
.
shadowElement
.
style
.
maxHeight
=
'
700px
'
;
this
.
element
.
style
.
height
=
`
${
dimension
.
height
}
px`
;
this
.
element
.
style
.
maxWidth
=
'
100%
'
;
this
.
element
.
style
.
maxHeight
=
'
700px
'
;
const
lineNum
=
cell
.
lineCount
;
const
totalHeight
=
Math
.
max
(
lineNum
+
1
,
5
)
*
21
;
cell
.
setDynamicHeight
(
totalHeight
+
32
+
dimension
.
height
);
this
.
notebookHandler
.
layoutElement
(
cell
,
totalHeight
+
32
+
dimension
.
height
);
}));
this
.
_localStore
.
add
(
this
.
webview
.
onDidWheel
(
e
=>
{
this
.
notebookHandler
.
triggerWheel
(
e
);
}));
}
public
updateShadowElement
(
element
:
HTMLElement
)
{
this
.
shadowElement
=
element
;
if
(
this
.
_dimension
)
{
this
.
shadowElement
.
style
.
minWidth
=
`
${
this
.
_dimension
.
width
}
px`
;
this
.
shadowElement
.
style
.
height
=
`
${
this
.
_dimension
.
height
}
px`
;
this
.
shadowElement
.
style
.
maxWidth
=
'
100%
'
;
this
.
shadowElement
.
style
.
maxHeight
=
'
700px
'
;
const
lineNum
=
this
.
cell
.
lineCount
;
const
totalHeight
=
Math
.
max
(
lineNum
+
1
,
5
)
*
21
;
this
.
cell
.
setDynamicHeight
(
totalHeight
+
32
+
this
.
_dimension
.
height
);
this
.
notebookHandler
.
layoutElement
(
this
.
cell
,
totalHeight
+
32
+
this
.
_dimension
.
height
);
}
}
private
_createInset
(
webviewService
:
IWebviewService
,
content
:
string
)
{
const
webview
=
webviewService
.
createWebview
(
''
+
UUID
.
generateUuid
(),
{
enableFindWidget
:
false
,
},
{
allowScripts
:
true
});
webview
.
html
=
content
;
return
webview
;
}
}
src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts
浏览文件 @
3e2c2fe5
...
...
@@ -11,7 +11,6 @@ import { NotebookEditorInput } from 'vs/workbench/contrib/notebook/browser/noteb
import
{
IEditorService
,
IOpenEditorOverride
}
from
'
vs/workbench/services/editor/common/editorService
'
;
import
{
IInstantiationService
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
Extensions
as
WorkbenchExtensions
,
IWorkbenchContribution
,
IWorkbenchContributionsRegistry
}
from
'
vs/workbench/common/contributions
'
;
import
{
IDisposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
IEditorInput
}
from
'
vs/workbench/common/editor
'
;
import
{
IEditorOptions
,
ITextEditorOptions
}
from
'
vs/platform/editor/common/editor
'
;
import
{
endsWith
}
from
'
vs/base/common/strings
'
;
...
...
@@ -30,7 +29,6 @@ Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
);
export
class
NotebookContribution
implements
IWorkbenchContribution
{
private
editorOpeningListener
:
IDisposable
|
undefined
;
private
_resourceMapping
:
Map
<
string
,
NotebookEditorInput
>
=
new
Map
<
string
,
NotebookEditorInput
>
();
constructor
(
...
...
@@ -38,7 +36,7 @@ export class NotebookContribution implements IWorkbenchContribution {
@
IInstantiationService
private
readonly
instantiationService
:
IInstantiationService
)
{
this
.
editor
OpeningListener
=
this
.
editor
Service
.
overrideOpenEditor
((
editor
,
options
,
group
)
=>
this
.
onEditorOpening
(
editor
,
options
,
group
));
this
.
editorService
.
overrideOpenEditor
((
editor
,
options
,
group
)
=>
this
.
onEditorOpening
(
editor
,
options
,
group
));
}
private
onEditorOpening
(
editor
:
IEditorInput
,
options
:
IEditorOptions
|
ITextEditorOptions
|
undefined
,
group
:
IEditorGroup
):
IOpenEditorOverride
|
undefined
{
...
...
src/vs/workbench/contrib/notebook/browser/notebookEditor.ts
浏览文件 @
3e2c2fe5
...
...
@@ -20,93 +20,19 @@ import { WorkbenchList } from 'vs/platform/list/browser/listService';
import
{
IModeService
}
from
'
vs/editor/common/services/modeService
'
;
import
{
NotebookHandler
,
ViewCell
,
MarkdownCellRenderer
,
CodeCellRenderer
,
NotebookCellListDelegate
}
from
'
vs/workbench/contrib/notebook/browser/cellRenderer
'
;
import
{
IEditorGroup
}
from
'
vs/workbench/services/editor/common/editorGroupsService
'
;
import
{
IWebviewService
,
WebviewElement
}
from
'
vs/workbench/contrib/webview/browser/webview
'
;
import
*
as
UUID
from
'
vs/base/common/uuid
'
;
import
{
IWebviewService
}
from
'
vs/workbench/contrib/webview/browser/webview
'
;
import
{
WebviewContentWidget
}
from
'
vs/workbench/contrib/notebook/browser/contentWidget
'
;
import
{
IMouseWheelEvent
}
from
'
vs/base/browser/mouseEvent
'
;
const
$
=
DOM
.
$
;
export
interface
IContentWidget
{
offset
:
number
;
cell
:
ViewCell
;
element
:
HTMLElement
;
webview
:
WebviewElement
;
}
export
class
WebviewContentWidget
implements
IContentWidget
{
public
element
:
HTMLElement
;
public
webview
:
WebviewElement
;
private
_dimension
:
DOM
.
Dimension
|
null
=
null
;
constructor
(
public
shadowElement
:
HTMLElement
,
public
cell
:
ViewCell
,
public
offset
:
number
,
webviewService
:
IWebviewService
,
shadowContent
:
string
,
public
notebookHandler
:
NotebookHandler
)
{
this
.
element
=
document
.
createElement
(
'
div
'
);
this
.
element
.
style
.
width
=
'
calc(100% - 36px)
'
;
this
.
element
.
style
.
height
=
'
700px
'
;
this
.
element
.
style
.
position
=
'
absolute
'
;
this
.
element
.
style
.
margin
=
'
0px 24px 0px 24px
'
;
this
.
webview
=
this
.
_createInset
(
webviewService
,
shadowContent
);
this
.
webview
.
mountTo
(
this
.
element
);
this
.
webview
.
onDidSetInitialDimension
(
dimension
=>
{
this
.
_dimension
=
dimension
;
// this.shadowElement.style.minWidth = `${dimension.width}px`;
this
.
shadowElement
.
style
.
height
=
`
${
dimension
.
height
}
px`
;
this
.
shadowElement
.
style
.
maxWidth
=
'
100%
'
;
this
.
shadowElement
.
style
.
maxHeight
=
'
700px
'
;
// this.element.style.minWidth= `${dimension.width}px`;
this
.
element
.
style
.
height
=
`
${
dimension
.
height
}
px`
;
this
.
element
.
style
.
maxWidth
=
'
100%
'
;
this
.
element
.
style
.
maxHeight
=
'
700px
'
;
const
lineNum
=
cell
.
lineCount
;
const
totalHeight
=
Math
.
max
(
lineNum
+
1
,
5
)
*
21
;
cell
.
setDynamicHeight
(
totalHeight
+
32
+
dimension
.
height
);
notebookHandler
.
layoutElement
(
cell
,
totalHeight
+
32
+
dimension
.
height
);
});
}
public
updateShadowElement
(
element
:
HTMLElement
)
{
this
.
shadowElement
=
element
;
if
(
this
.
_dimension
)
{
this
.
shadowElement
.
style
.
minWidth
=
`
${
this
.
_dimension
.
width
}
px`
;
this
.
shadowElement
.
style
.
height
=
`
${
this
.
_dimension
.
height
}
px`
;
this
.
shadowElement
.
style
.
maxWidth
=
'
100%
'
;
this
.
shadowElement
.
style
.
maxHeight
=
'
700px
'
;
const
lineNum
=
this
.
cell
.
lineCount
;
const
totalHeight
=
Math
.
max
(
lineNum
+
1
,
5
)
*
21
;
this
.
cell
.
setDynamicHeight
(
totalHeight
+
32
+
this
.
_dimension
.
height
);
this
.
notebookHandler
.
layoutElement
(
this
.
cell
,
totalHeight
+
32
+
this
.
_dimension
.
height
);
}
}
private
_createInset
(
webviewService
:
IWebviewService
,
content
:
string
)
{
const
webview
=
webviewService
.
createWebview
(
''
+
UUID
.
generateUuid
(),
{
enableFindWidget
:
false
,
},
{
allowScripts
:
true
});
webview
.
html
=
content
;
return
webview
;
}
dispose
()
{
}
}
export
class
NotebookEditor
extends
BaseEditor
implements
NotebookHandler
{
static
readonly
ID
:
string
=
'
workbench.editor.notebook
'
;
private
rootElement
!
:
HTMLElement
;
private
body
!
:
HTMLElement
;
private
contentWidgets
!
:
HTMLElement
;
private
contentWidgetsMap
:
Map
<
ViewCell
,
WebviewContentWidget
>
=
new
Map
();
private
contentWidgetsPool
:
WebviewContentWidget
[]
=
[];
private
list
:
WorkbenchList
<
ViewCell
>
|
undefined
;
private
model
:
NotebookEditorModel
|
undefined
;
...
...
@@ -189,8 +115,12 @@ export class NotebookEditor extends BaseEditor implements NotebookHandler {
}
);
this
.
list
.
onDidScroll
((
e
)
=>
{
this
.
_register
(
this
.
list
.
onDidScroll
((
e
)
=>
{
this
.
contentWidgetsMap
.
forEach
((
value
,
cell
)
=>
{
if
(
value
.
detachedFromViewEvents
)
{
return
;
}
let
index
=
this
.
model
!
.
getNotebook
().
cells
.
indexOf
(
cell
.
cell
);
let
top
=
this
.
list
?.
getElementTop
(
index
);
if
(
top
!==
null
&&
top
!==
undefined
)
{
...
...
@@ -199,13 +129,35 @@ export class NotebookEditor extends BaseEditor implements NotebookHandler {
domElement
.
style
.
top
=
`
${
-
scrollTop
+
top
+
value
.
offset
}
px`
;
}
});
});
}));
this
.
_register
(
this
.
list
);
}
triggerWheel
(
event
:
IMouseWheelEvent
)
{
this
.
list
?.
triggerScrollFromMouseWheelEvent
(
event
);
}
createContentWidget
(
cell
:
ViewCell
,
shadowContent
:
string
,
shadowElement
:
HTMLElement
,
offset
:
number
)
{
let
zone
=
this
.
contentWidgetsMap
.
get
(
cell
);
if
(
!
zone
)
{
let
existingContentWidget
=
this
.
contentWidgetsPool
.
pop
();
if
(
existingContentWidget
)
{
existingContentWidget
.
detachedFromViewEvents
=
false
;
existingContentWidget
.
updateInitialization
(
shadowElement
,
cell
,
offset
,
shadowContent
);
this
.
contentWidgetsMap
.
set
(
cell
,
existingContentWidget
);
let
index
=
this
.
model
!
.
getNotebook
().
cells
.
indexOf
(
cell
.
cell
);
let
top
=
this
.
list
?.
getElementTop
(
index
);
if
(
top
!==
null
&&
top
!==
undefined
)
{
let
domElement
=
existingContentWidget
.
element
;
let
scrollTop
=
this
.
list
?.
scrollTop
||
0
;
domElement
.
style
.
top
=
`
${
-
scrollTop
+
top
+
existingContentWidget
.
offset
}
px`
;
}
return
;
}
let
contentWidget
=
new
WebviewContentWidget
(
shadowElement
,
cell
,
...
...
@@ -222,6 +174,28 @@ export class NotebookEditor extends BaseEditor implements NotebookHandler {
}
}
disposeViewCell
(
cell
:
ViewCell
)
{
let
zone
=
this
.
contentWidgetsMap
.
get
(
cell
);
if
(
zone
)
{
// we are going to dispose a view who has a webview
if
(
!
zone
.
webview
.
containsScript
)
{
// this view can be disposed
zone
.
detachedFromViewEvents
=
true
;
zone
.
element
.
style
.
top
=
'
-2400px
'
;
zone
.
element
.
style
.
height
=
'
700px
'
;
if
(
this
.
contentWidgetsPool
.
length
<
10
)
{
this
.
contentWidgetsPool
.
push
(
zone
);
this
.
contentWidgetsMap
.
delete
(
cell
);
}
else
{
this
.
contentWidgets
.
removeChild
(
zone
.
element
);
this
.
contentWidgetsMap
.
delete
(
cell
);
}
}
}
}
onHide
()
{
super
.
onHide
();
...
...
@@ -268,6 +242,7 @@ export class NotebookEditor extends BaseEditor implements NotebookHandler {
// list.splice -> renderElement -> resize -> layoutElement
// above flow will actually break how list view renders it self as it messes up with the internal state
// instead we run the layout update in next tick
//. @TODO @rebornix, it should be batched.
let
index
=
this
.
model
!
.
getNotebook
().
cells
.
indexOf
(
cell
.
cell
);
this
.
list
?.
updateDynamicHeight
(
index
,
cell
,
height
);
},
0
);
...
...
src/vs/workbench/contrib/notebook/browser/outputRenderer.ts
浏览文件 @
3e2c2fe5
...
...
@@ -97,12 +97,10 @@ class RichDisplayRenderer implements IMimeRenderer {
outputNode
.
appendChild
(
display
);
hasDynamicHeight
=
true
;
}
else
if
(
output
.
data
&&
output
.
data
[
'
text/html
'
])
{
let
data
=
output
.
data
[
'
text/html
'
];
let
str
=
isArray
(
data
)
?
data
.
join
(
''
)
:
data
;
display
.
style
.
width
=
'
100%
'
;
display
.
style
.
height
=
'
100px
'
;
// display.style.backgroundColor = 'gray';
hasDynamicHeight
=
true
;
outputNode
.
appendChild
(
display
);
...
...
src/vs/workbench/contrib/webview/browser/baseWebviewElement.ts
浏览文件 @
3e2c2fe5
...
...
@@ -13,6 +13,9 @@ import { WebviewExtensionDescription, WebviewOptions, WebviewContentOptions } fr
import
{
areWebviewInputOptionsEqual
}
from
'
vs/workbench/contrib/webview/browser/webviewWorkbenchService
'
;
import
{
WebviewThemeDataProvider
}
from
'
vs/workbench/contrib/webview/common/themeing
'
;
import
{
IWorkbenchEnvironmentService
}
from
'
vs/workbench/services/environment/common/environmentService
'
;
import
{
IMouseWheelEvent
}
from
'
vs/base/browser/mouseEvent
'
;
import
{
VSBuffer
}
from
'
vs/base/common/buffer
'
;
import
{
StopWatch
}
from
'
vs/base/common/stopwatch
'
;
export
const
enum
WebviewMessageChannels
{
onmessage
=
'
onmessage
'
,
...
...
@@ -25,7 +28,10 @@ export const enum WebviewMessageChannels {
loadResource
=
'
load-resource
'
,
loadLocalhost
=
'
load-localhost
'
,
webviewReady
=
'
webview-ready
'
,
didSetInitialDimension
=
'
did-set-initial-dimension
'
didSetInitialDimension
=
'
did-set-initial-dimension
'
,
containsScripts
=
'
content-contains-scripts
'
,
wheel
=
'
did-scroll-wheel
'
,
ack
=
'
speed-test-ack
'
}
interface
IKeydownEvent
{
...
...
@@ -59,6 +65,8 @@ export abstract class BaseWebview<T extends HTMLElement> extends Disposable {
public
extension
:
WebviewExtensionDescription
|
undefined
;
private
sw
:
StopWatch
|
null
=
null
;
constructor
(
// TODO: matb, this should not be protected. The only reason it needs to be is that the base class ends up using it in the call to createElement
protected
readonly
id
:
string
,
...
...
@@ -122,6 +130,19 @@ export abstract class BaseWebview<T extends HTMLElement> extends Disposable {
this
.
handleInitialDimension
(
dimension
);
}));
this
.
_register
(
this
.
on
(
WebviewMessageChannels
.
containsScripts
,
(
containsScript
:
boolean
)
=>
{
this
.
containsScript
=
containsScript
;
}));
this
.
_register
(
this
.
on
(
WebviewMessageChannels
.
wheel
,
(
event
:
IMouseWheelEvent
)
=>
{
this
.
_onDidWheel
.
fire
(
event
);
}));
this
.
_register
(
this
.
on
(
WebviewMessageChannels
.
ack
,
(
buf
)
=>
{
this
.
sw
!
.
stop
();
console
.
log
(
this
.
_printSpeed
(
this
.
_convert
(
2
*
10
*
1024
*
1024
,
this
.
sw
!
.
elapsed
())));
}));
this
.
_register
(
this
.
on
(
WebviewMessageChannels
.
didBlur
,
()
=>
{
this
.
handleFocusChange
(
false
);
}));
...
...
@@ -137,6 +158,20 @@ export abstract class BaseWebview<T extends HTMLElement> extends Disposable {
this
.
_register
(
webviewThemeDataProvider
.
onThemeDataChanged
(
this
.
style
,
this
));
}
private
_convert
(
byteCount
:
number
,
elapsedMillis
:
number
):
number
{
return
(
byteCount
*
1000
*
8
)
/
elapsedMillis
;
}
private
_printSpeed
(
n
:
number
):
string
{
if
(
n
<=
1024
)
{
return
`
${
n
}
bps`
;
}
if
(
n
<
1024
*
1024
)
{
return
`
${(
n
/
1024
).
toFixed
(
1
)}
kbps`
;
}
return
`
${(
n
/
1024
/
1024
).
toFixed
(
1
)}
Mbps`
;
}
dispose
():
void
{
if
(
this
.
element
)
{
this
.
element
.
remove
();
...
...
@@ -158,6 +193,9 @@ export abstract class BaseWebview<T extends HTMLElement> extends Disposable {
private
readonly
_onDidScroll
=
this
.
_register
(
new
Emitter
<
{
readonly
scrollYPercentage
:
number
;
}
>
());
public
readonly
onDidScroll
=
this
.
_onDidScroll
.
event
;
private
readonly
_onDidWheel
=
this
.
_register
(
new
Emitter
<
IMouseWheelEvent
>
());
public
readonly
onDidWheel
=
this
.
_onDidWheel
.
event
;
private
readonly
_onDidUpdateState
=
this
.
_register
(
new
Emitter
<
string
|
undefined
>
());
public
readonly
onDidUpdateState
=
this
.
_onDidUpdateState
.
event
;
...
...
@@ -167,6 +205,8 @@ export abstract class BaseWebview<T extends HTMLElement> extends Disposable {
private
readonly
_onDidSetInitialDimension
=
this
.
_register
(
new
Emitter
<
Dimension
>
());
public
readonly
onDidSetInitialDimension
=
this
.
_onDidSetInitialDimension
.
event
;
public
containsScript
:
boolean
=
false
;
public
sendMessage
(
data
:
any
):
void
{
this
.
_send
(
'
message
'
,
data
);
}
...
...
@@ -221,6 +261,9 @@ export abstract class BaseWebview<T extends HTMLElement> extends Disposable {
state
:
this
.
content
.
state
,
};
this
.
doUpdateContent
();
setTimeout
(()
=>
{
this
.
speedTest
();
},
3000
);
}
public
set
contentOptions
(
options
:
WebviewContentOptions
)
{
...
...
@@ -248,6 +291,18 @@ export abstract class BaseWebview<T extends HTMLElement> extends Disposable {
this
.
_send
(
'
initial-scroll-position
'
,
value
);
}
public
speedTest
()
{
const
SIZE
=
10
*
1024
*
1024
;
// 10MB
let
buff
=
VSBuffer
.
alloc
(
SIZE
);
let
value
=
Math
.
random
()
%
256
;
for
(
let
i
=
0
;
i
<
SIZE
;
i
++
)
{
buff
.
writeUInt8
(
value
,
i
);
}
this
.
sw
=
StopWatch
.
create
(
true
);
this
.
_send
(
'
speedTest
'
,
buff
.
buffer
);
}
private
doUpdateContent
()
{
this
.
_send
(
'
content
'
,
{
contents
:
this
.
content
.
html
,
...
...
src/vs/workbench/contrib/webview/browser/dynamicWebviewEditorOverlay.ts
浏览文件 @
3e2c2fe5
...
...
@@ -10,11 +10,15 @@ import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import
{
IWebviewService
,
Webview
,
WebviewContentOptions
,
WebviewEditorOverlay
,
WebviewElement
,
WebviewOptions
,
WebviewExtensionDescription
}
from
'
vs/workbench/contrib/webview/browser/webview
'
;
import
{
IWorkbenchLayoutService
}
from
'
vs/workbench/services/layout/browser/layoutService
'
;
import
{
Dimension
}
from
'
vs/base/browser/dom
'
;
import
{
IMouseWheelEvent
}
from
'
vs/base/browser/mouseEvent
'
;
/**
* Webview editor overlay that creates and destroys the underlying webview as needed.
*/
export
class
DynamicWebviewEditorOverlay
extends
Disposable
implements
WebviewEditorOverlay
{
private
readonly
_onDidWheel
=
this
.
_register
(
new
Emitter
<
IMouseWheelEvent
>
());
public
readonly
onDidWheel
=
this
.
_onDidWheel
.
event
;
private
readonly
_onDidSetInitialDimension
=
this
.
_register
(
new
Emitter
<
Dimension
>
());
public
readonly
onDidSetInitialDimension
=
this
.
_onDidSetInitialDimension
.
event
;
...
...
@@ -31,6 +35,7 @@ export class DynamicWebviewEditorOverlay extends Disposable implements WebviewEd
private
_options
:
WebviewOptions
;
private
_owner
:
any
=
undefined
;
containsScript
:
boolean
=
false
;
public
constructor
(
private
readonly
id
:
string
,
...
...
src/vs/workbench/contrib/webview/browser/pre/main.js
浏览文件 @
3e2c2fe5
...
...
@@ -60,7 +60,6 @@
font-weight: var(--vscode-font-weight);
font-size: var(--vscode-font-size);
margin: 0;
padding: 0 20px;
height: 100%;
width: 100%;
}
...
...
@@ -271,6 +270,21 @@
};
let
isHandlingScroll
=
false
;
const
handleWheel
=
(
event
)
=>
{
if
(
isHandlingScroll
)
{
return
;
}
host
.
postMessage
(
'
did-scroll-wheel
'
,
{
deltaMode
:
event
.
deltaMode
,
deltaX
:
event
.
deltaX
,
deltaY
:
event
.
deltaY
,
deltaZ
:
event
.
deltaZ
,
detail
:
event
.
detail
,
type
:
event
.
type
});
};
const
handleInnerScroll
=
(
event
)
=>
{
if
(
!
event
.
target
||
!
event
.
target
.
body
)
{
return
;
...
...
@@ -312,6 +326,7 @@
// apply default script
if
(
options
.
allowScripts
)
{
const
defaultScript
=
newDocument
.
createElement
(
'
script
'
);
defaultScript
.
id
=
'
_vscodeApiScript
'
;
defaultScript
.
textContent
=
getVsCodeApiScript
(
data
.
state
);
newDocument
.
head
.
prepend
(
defaultScript
);
}
...
...
@@ -453,6 +468,23 @@
},
0
);
});
const
checkScripts
=
(
document
)
=>
{
let
scripts
=
document
.
getElementsByTagName
(
'
script
'
);
if
(
scripts
.
length
>
1
)
{
return
true
;
}
if
(
scripts
[
0
].
id
!==
'
_vscodeApiScript
'
)
{
return
true
;
}
// no scripts
let
iframes
=
document
.
getElementsByTagName
(
'
iframe
'
);
return
iframes
.
length
>
0
;
};
const
onLoad
=
(
contentDocument
,
contentWindow
)
=>
{
if
(
contentDocument
&&
contentDocument
.
body
)
{
// Workaround for https://github.com/Microsoft/vscode/issues/12865
...
...
@@ -475,8 +507,10 @@
}
host
.
postMessage
(
'
did-set-initial-dimension
'
,
{
width
:
newFrame
.
contentWindow
.
document
.
body
.
scrollWidth
,
height
:
newFrame
.
contentWindow
.
document
.
body
.
scrollHeight
});
host
.
postMessage
(
'
content-contains-scripts
'
,
checkScripts
(
newFrame
.
contentWindow
.
document
));
contentWindow
.
addEventListener
(
'
scroll
'
,
handleInnerScroll
);
contentWindow
.
addEventListener
(
'
wheel
'
,
handleWheel
);
pendingMessages
.
forEach
((
data
)
=>
{
contentWindow
.
postMessage
(
data
,
'
*
'
);
...
...
@@ -545,6 +579,9 @@
initData
.
initialScrollProgress
=
progress
;
});
host
.
onMessage
(
'
speedTest
'
,
(
_event
,
buf
)
=>
{
host
.
postMessage
(
'
speed-test-ack
'
,
buf
);
});
trackFocus
({
onFocus
:
()
=>
host
.
postMessage
(
'
did-focus
'
),
...
...
src/vs/workbench/contrib/webview/browser/webview.ts
浏览文件 @
3e2c2fe5
...
...
@@ -12,6 +12,7 @@ import * as nls from 'vs/nls';
import
{
RawContextKey
}
from
'
vs/platform/contextkey/common/contextkey
'
;
import
{
ExtensionIdentifier
}
from
'
vs/platform/extensions/common/extensions
'
;
import
{
createDecorator
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
IMouseWheelEvent
}
from
'
vs/base/browser/mouseEvent
'
;
/**
* Set when the find widget in a webview is visible.
...
...
@@ -69,11 +70,13 @@ export interface Webview extends IDisposable {
extension
:
WebviewExtensionDescription
|
undefined
;
initialScrollProgress
:
number
;
state
:
string
|
undefined
;
containsScript
:
boolean
;
readonly
onDidFocus
:
Event
<
void
>
;
readonly
onDidSetInitialDimension
:
Event
<
Dimension
>
;
readonly
onDidClickLink
:
Event
<
string
>
;
readonly
onDidScroll
:
Event
<
{
scrollYPercentage
:
number
}
>
;
readonly
onDidWheel
:
Event
<
IMouseWheelEvent
>
;
readonly
onDidUpdateState
:
Event
<
string
|
undefined
>
;
readonly
onMessage
:
Event
<
any
>
;
readonly
onMissingCsp
:
Event
<
ExtensionIdentifier
>
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录