+
diff --git a/src/sql/workbench/parts/notebook/cellViews/textCell.component.ts b/src/sql/workbench/parts/notebook/cellViews/textCell.component.ts
index 969ceb5600..fe88133091 100644
--- a/src/sql/workbench/parts/notebook/cellViews/textCell.component.ts
+++ b/src/sql/workbench/parts/notebook/cellViews/textCell.component.ts
@@ -154,6 +154,10 @@ export class TextCellComponent extends CellView implements OnInit, OnChanges {
return this.model.trustedMode;
}
+ public get notebookUri(): URI {
+ return this.model.notebookUri;
+ }
+
/**
* Updates the preview of markdown component with latest changes
* If content is empty and in non-edit mode, default it to 'Double-click to edit'
diff --git a/src/sql/workbench/parts/notebook/notebook.component.ts b/src/sql/workbench/parts/notebook/notebook.component.ts
index 92775a5432..bb1897a1af 100644
--- a/src/sql/workbench/parts/notebook/notebook.component.ts
+++ b/src/sql/workbench/parts/notebook/notebook.component.ts
@@ -24,7 +24,7 @@ import { AngularDisposable } from 'sql/base/node/lifecycle';
import { CellTypes, CellType } from 'sql/workbench/parts/notebook/models/contracts';
import { ICellModel, IModelFactory, INotebookModel, NotebookContentChange } from 'sql/workbench/parts/notebook/models/modelInterfaces';
import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
-import { INotebookService, INotebookParams, INotebookManager, INotebookEditor, DEFAULT_NOTEBOOK_PROVIDER, SQL_NOTEBOOK_PROVIDER } from 'sql/workbench/services/notebook/common/notebookService';
+import { INotebookService, INotebookParams, INotebookManager, INotebookEditor, INotebookSection, DEFAULT_NOTEBOOK_PROVIDER, SQL_NOTEBOOK_PROVIDER } from 'sql/workbench/services/notebook/common/notebookService';
import { IBootstrapParams } from 'sql/platform/bootstrap/node/bootstrapService';
import { NotebookModel } from 'sql/workbench/parts/notebook/models/notebookModel';
import { ModelFactory } from 'sql/workbench/parts/notebook/models/modelFactory';
@@ -582,4 +582,48 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
}
}
+ getSections(): INotebookSection[] {
+ return this.getSectionElements();
+ }
+
+ private getSectionElements(): NotebookSection[] {
+ let headers: NotebookSection[] = [];
+ let el: HTMLElement = this.container.nativeElement;
+ let headerElements = el.querySelectorAll('h1, h2, h3, h4, h5, h6');
+ for (let i = 0; i < headerElements.length; i++) {
+ let headerEl = headerElements[i] as HTMLElement;
+ if (headerEl['id']) {
+ headers.push(new NotebookSection(headerEl));
+ }
+ }
+ return headers;
+ }
+
+ navigateToSection(id: string): void {
+ id = id.toLowerCase();
+ let section = this.getSectionElements().find(s => s.relativeUri && s.relativeUri.toLowerCase() === id);
+ if (section) {
+ // Scroll this section to the top of the header instead of just bringing header into view.
+ let scrollTop = jQuery(section.headerEl).offset().top;
+ (
this.container.nativeElement).scrollTo({
+ top: scrollTop,
+ behavior: 'smooth'
+ });
+ section.headerEl.focus();
+ }
+ }
}
+
+class NotebookSection implements INotebookSection {
+
+ constructor(public headerEl: HTMLElement) {
+ }
+
+ get relativeUri(): string {
+ return this.headerEl['id'];
+ }
+
+ get header(): string {
+ return this.headerEl.textContent;
+ }
+}
\ No newline at end of file
diff --git a/src/sql/workbench/parts/notebook/outputs/markdownOutput.component.html b/src/sql/workbench/parts/notebook/outputs/markdownOutput.component.html
index 8d9fd68187..7e1dc70754 100644
--- a/src/sql/workbench/parts/notebook/outputs/markdownOutput.component.html
+++ b/src/sql/workbench/parts/notebook/outputs/markdownOutput.component.html
@@ -1,5 +1,5 @@
-
diff --git a/src/sql/workbench/parts/notebook/outputs/markdownOutput.component.ts b/src/sql/workbench/parts/notebook/outputs/markdownOutput.component.ts
index 9c09cac652..70852f71af 100644
--- a/src/sql/workbench/parts/notebook/outputs/markdownOutput.component.ts
+++ b/src/sql/workbench/parts/notebook/outputs/markdownOutput.component.ts
@@ -19,6 +19,7 @@ import { convertVscodeResourceToFileInSubDirectories, useInProcMarkdown } from '
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { NotebookMarkdownRenderer } from 'sql/workbench/parts/notebook/outputs/notebookMarkdown';
+import { URI } from 'vs/base/common/uri';
@Component({
selector: MarkdownOutputComponent.SELECTOR,
@@ -75,6 +76,10 @@ export class MarkdownOutputComponent extends AngularDisposable implements IMimeC
return this._bundleOptions && this._bundleOptions.trusted;
}
+ public get notebookUri(): URI {
+ return this.cellModel.notebookModel.notebookUri;
+ }
+
//Gets sanitizer from ISanitizer interface
private get sanitizer(): ISanitizer {
if (this._sanitizer) {
diff --git a/src/sql/workbench/services/notebook/common/notebookService.ts b/src/sql/workbench/services/notebook/common/notebookService.ts
index 7b8663d499..7dcef36598 100644
--- a/src/sql/workbench/services/notebook/common/notebookService.ts
+++ b/src/sql/workbench/services/notebook/common/notebookService.ts
@@ -90,6 +90,12 @@ export interface INotebookService {
*/
serializeNotebookStateChange(notebookUri: URI, changeType: NotebookChangeType): void;
+ /**
+ *
+ * @param notebookUri URI of the notebook to navigate to
+ * @param sectionId ID of the section to navigate to
+ */
+ navigateTo(notebookUri: URI, sectionId: string): void;
}
export interface INotebookProvider {
@@ -117,6 +123,15 @@ export interface INotebookParams extends IBootstrapParams {
modelFactory?: ModelFactory;
}
+/**
+ * Defines a section in a notebook as the header text for that section,
+ * the relative URI that can be used to link to it inside Notebook documents
+ */
+export interface INotebookSection {
+ header: string;
+ relativeUri: string;
+}
+
export interface INotebookEditor {
readonly notebookParams: INotebookParams;
readonly id: string;
@@ -131,4 +146,6 @@ export interface INotebookEditor {
runAllCells(startCell?: ICellModel, endCell?: ICellModel): Promise
;
clearOutput(cell: ICellModel): Promise;
clearAllOutputs(): Promise;
+ getSections(): INotebookSection[];
+ navigateToSection(sectionId: string): void;
}
diff --git a/src/sql/workbench/services/notebook/common/notebookServiceImpl.ts b/src/sql/workbench/services/notebook/common/notebookServiceImpl.ts
index afe7130d48..4f413558da 100644
--- a/src/sql/workbench/services/notebook/common/notebookServiceImpl.ts
+++ b/src/sql/workbench/services/notebook/common/notebookServiceImpl.ts
@@ -619,4 +619,11 @@ export class NotebookService extends Disposable implements INotebookService {
}
}
}
+
+ navigateTo(notebookUri: URI, sectionId: string): void {
+ let editor = this._editors.get(notebookUri.toString());
+ if (editor) {
+ editor.navigateToSection(sectionId);
+ }
+ }
}