From a12b762a5283cf254c017b5d8c082ec48fd5c1fe Mon Sep 17 00:00:00 2001 From: Ian Rose Date: Sat, 8 Jun 2019 10:02:39 -0700 Subject: [PATCH 1/3] Don't append content in rendered output upon rerendering. --- packages/rendermime/src/widgets.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/rendermime/src/widgets.ts b/packages/rendermime/src/widgets.ts index 7c4e91d3b88f..5712fa7f3d80 100644 --- a/packages/rendermime/src/widgets.ts +++ b/packages/rendermime/src/widgets.ts @@ -63,10 +63,21 @@ export abstract class RenderedCommon extends Widget * @param model - The mime model to render. * * @returns A promise which resolves when rendering is complete. + * + * #### Notes + * If the DOM node for this widget already has content, it is emptied + * before rendering. Subclasses that do not want this behavior + * (if, for instance, they are using DOM diffing), should override + * this method. */ async renderModel(model: IRenderMime.IMimeModel): Promise { // TODO compare model against old model for early bail? + // Empty any existing content in the node from previous renders + while (this.node.firstChild) { + this.node.removeChild(this.node.firstChild); + } + // Toggle the trusted class on the widget. this.toggleClass('jp-mod-trusted', model.trusted); From d25118bdcb8554ce3a6a3728a330bef5d0d25069 Mon Sep 17 00:00:00 2001 From: Ian Rose Date: Sat, 8 Jun 2019 10:41:08 -0700 Subject: [PATCH 2/3] Add tests checking that a model can be re-rendered correctly. --- tests/test-rendermime/src/factories.spec.ts | 43 +++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/tests/test-rendermime/src/factories.spec.ts b/tests/test-rendermime/src/factories.spec.ts index fc0b920ef8da..b846dc02bd3c 100644 --- a/tests/test-rendermime/src/factories.spec.ts +++ b/tests/test-rendermime/src/factories.spec.ts @@ -66,6 +66,16 @@ describe('rendermime/factories', () => { expect(w.node.innerHTML).to.equal('
x = 2 ** a
'); }); + it('should be re-renderable', async () => { + const f = textRendererFactory; + const mimeType = 'text/plain'; + const model = createModel(mimeType, 'x = 2 ** a'); + const w = f.createRenderer({ mimeType, ...defaultOptions }); + await w.renderModel(model); + await w.renderModel(model); + expect(w.node.innerHTML).to.equal('
x = 2 ** a
'); + }); + it('should output the correct HTML with ansi colors', async () => { const f = textRendererFactory; const source = 'There is no text but \x1b[01;41;32mtext\x1b[00m.\nWoo.'; @@ -116,6 +126,17 @@ describe('rendermime/factories', () => { await w.renderModel(model); expect(w.node.textContent).to.equal(source); }); + + it('should be re-renderable', async () => { + const source = 'sumlimits_{i=0}^{infty} \frac{1}{n^2}'; + const f = latexRendererFactory; + const mimeType = 'text/latex'; + const model = createModel(mimeType, source); + const w = f.createRenderer({ mimeType, ...defaultOptions }); + await w.renderModel(model); + await w.renderModel(model); + expect(w.node.textContent).to.equal(source); + }); }); }); @@ -174,6 +195,17 @@ describe('rendermime/factories', () => { expect(w.node.innerHTML).to.equal(source); }); + it('it should be re-renderable', async () => { + const f = markdownRendererFactory; + const source = '

hello

'; + const mimeType = 'text/markdown'; + const model = createModel(mimeType, source); + const w = f.createRenderer({ mimeType, ...defaultOptions }); + await w.renderModel(model); + await w.renderModel(model); + expect(w.node.innerHTML).to.equal(source); + }); + it('should add header anchors', async () => { const source = require('../../../examples/filebrowser/sample.md') .default as string; @@ -229,6 +261,17 @@ describe('rendermime/factories', () => { expect(w.node.innerHTML).to.equal('

This is great

'); }); + it('should be re-renderable', async () => { + const f = htmlRendererFactory; + const source = '

This is great

'; + const mimeType = 'text/html'; + const model = createModel(mimeType, source); + const w = f.createRenderer({ mimeType, ...defaultOptions }); + await w.renderModel(model); + await w.renderModel(model); + expect(w.node.innerHTML).to.equal('

This is great

'); + }); + // TODO we are disabling script execution for now. it.skip('should execute a script tag when attached', () => { const source = ''; From a918f2c254f8259c320bdcaf0b16c472b44b511c Mon Sep 17 00:00:00 2001 From: Ian Rose Date: Sat, 8 Jun 2019 12:41:12 -0700 Subject: [PATCH 3/3] Clarify comment. --- packages/rendermime/src/widgets.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rendermime/src/widgets.ts b/packages/rendermime/src/widgets.ts index 5712fa7f3d80..8a1b7c9f168e 100644 --- a/packages/rendermime/src/widgets.ts +++ b/packages/rendermime/src/widgets.ts @@ -68,7 +68,7 @@ export abstract class RenderedCommon extends Widget * If the DOM node for this widget already has content, it is emptied * before rendering. Subclasses that do not want this behavior * (if, for instance, they are using DOM diffing), should override - * this method. + * this method and not call `super.renderModel()`. */ async renderModel(model: IRenderMime.IMimeModel): Promise { // TODO compare model against old model for early bail?