Skip to content

Commit f4d83fe

Browse files
tlouissedaKmoR
authored andcommitted
feat(mdjs-preview): provide overridable renderFunction
1 parent 4ac6210 commit f4d83fe

File tree

7 files changed

+172
-256
lines changed

7 files changed

+172
-256
lines changed

.changeset/tiny-ties-press.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@mdjs/mdjs-preview': patch
3+
---
4+
5+
add overridable `renderFunction` to mdjs-preview

docs/docs/markdown-javascript/preview.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,33 @@ class DemoElement extends HTMLElement {
226226
customElements.define('demo-element', DemoElement);
227227
```
228228

229+
## Extending mdjs-preview
230+
231+
It is possible to define a custom version of mdjs-preview in order to add functionality, change
232+
its appearance of make it run in 'hybrid mode' (accepting both lit1 and -2 TemplateResults).
233+
The example below shows how the latter can be achieved by providing a custom render function.
234+
Note that we define `mdjs-preview` as the custom element name. We need to make sure that this
235+
file is executed before the original mdjs-preview definition file is executed.
236+
237+
```js
238+
import { MdJsPreview } from '@mdjs/mdjs-preview';
239+
import { render as render2 } from 'lit';
240+
import { isTemplateResult as isTemplateResult2 } from 'lit/directive-helpers.js';
241+
import { render as render1 } from 'lit-html';
242+
243+
export class HybridLitMdjsPreview extends MdJsPreview {
244+
get renderFunction() {
245+
return function renderHybrid(html, container, options) {
246+
if (isTemplateResult2(html)) {
247+
render2(html, container, options);
248+
} else {
249+
render1(html, container, options);
250+
}
251+
};
252+
}
253+
customElements.define('mdjs-preview', HybridLitMdjsPreview);
254+
```
255+
229256
```js script
230257
import '@rocket/launch/inline-notification/inline-notification.js';
231258
```

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
"setup": "npm run setup:ts-configs && npm run build:packages",
3434
"setup:patches": "npx patch-package",
3535
"setup:ts-configs": "node scripts/generate-ts-configs.mjs",
36-
"xprestart": "yarn analyze",
3736
"start": "node --trace-warnings packages/cli/src/cli.js start",
3837
"test": "yarn test:node && yarn test:web",
3938
"test:node": "mocha \"packages/*/test-node/**/*.test.{ts,js,mjs,cjs}\" --timeout 5000 --reporter dot --exit",
@@ -44,12 +43,13 @@
4443
"types:copy": "node scripts/workspaces-scripts-bin.mjs types:copy",
4544
"update-dependency": "node scripts/update-dependency.js",
4645
"update-esm-entrypoints": "node scripts/update-esm-entrypoints.mjs && yarn format",
47-
"update-package-configs": "node scripts/update-package-configs.mjs && yarn format"
46+
"update-package-configs": "node scripts/update-package-configs.mjs && yarn format",
47+
"xprestart": "yarn analyze"
4848
},
4949
"devDependencies": {
5050
"@changesets/cli": "^2.20.0",
5151
"@custom-elements-manifest/analyzer": "^0.4.12",
52-
"@open-wc/testing": "^3.0.0-next.1",
52+
"@open-wc/testing": "^3.1.2",
5353
"@rollup/plugin-commonjs": "^17.0.0",
5454
"@rollup/plugin-json": "^4.1.0",
5555
"@rollup/plugin-typescript": "^8.1.0",

packages/mdjs-preview/src/MdJsPreview.js

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,38 @@ export class MdJsPreview extends ScopedElementsMixin(LitElement) {
7272
};
7373
}
7474

75+
/**
76+
* By default, the render of lit2 is provided, which is compatible with TemplateResults of lit2.
77+
* However, in contexts that need to run multiple versions of lit, it should be possible to
78+
* provide a specific render function, like renderHybrid, that internally checks, based on the
79+
* TemplateResult, whether the render function of lit 1 or 2 should called.
80+
* Overriding the render function would look like:
81+
*
82+
* @example
83+
* ```js
84+
* import { MdJsPreview } from '@mdjs/mdjs-preview';
85+
* import { render as render2 } from 'lit';
86+
* import { isTemplateResult as isTemplateResult2 } from 'lit/directive-helpers.js';
87+
* import { render as render1 } from 'lit-html';
88+
*
89+
* export class HybridLitMdjsPreview extends MdJsPreview {
90+
* get renderFunction() {
91+
* return function renderHybrid(html, container, options) {
92+
* if (isTemplateResult2(html)) {
93+
* render2(html, container, options);
94+
* } else {
95+
* render1(html, container, options);
96+
* }
97+
* };
98+
* }
99+
* }
100+
* customElements.define('mdjs-preview', HybridLitMdjsPreview);
101+
* ```
102+
*/
103+
get renderFunction() {
104+
return render;
105+
}
106+
75107
constructor() {
76108
super();
77109
/** @type {LitHtmlStoryFn} */
@@ -257,7 +289,7 @@ export class MdJsPreview extends ScopedElementsMixin(LitElement) {
257289
}
258290

259291
if (this.lightDomRenderTarget && changeProps.has('story')) {
260-
render(this.story({ shadowRoot: this }), this.lightDomRenderTarget);
292+
this.renderFunction(this.story({ shadowRoot: this }), this.lightDomRenderTarget);
261293
}
262294

263295
if (changeProps.has('platform') || changeProps.has('size')) {
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { expect, fixture, html } from '@open-wc/testing';
2+
import { html as storyHtml } from '@mdjs/mdjs-preview';
3+
import { MdJsPreview } from '@mdjs/mdjs-preview';
4+
import { render as render2 } from 'lit';
5+
import { isTemplateResult as isTemplateResult2 } from 'lit/directive-helpers.js';
6+
7+
/** @typedef {import('@mdjs/mdjs-preview').MdJsPreview} MdJsPreview */
8+
9+
describe('mdjs-preview Subclasser', () => {
10+
it('will expose a render function getter to override in extensions', async () => {
11+
let isCalled = false;
12+
class HybridLitMdjsPreview extends MdJsPreview {
13+
get renderFunction() {
14+
return function renderStrict(html, container, options) {
15+
isCalled = true;
16+
if (isTemplateResult2(html)) {
17+
render2(html, container, options);
18+
} else {
19+
throw new Error('[mdjs-preview]: Only lit2 allowed');
20+
}
21+
};
22+
}
23+
}
24+
customElements.define('mdjs-preview', HybridLitMdjsPreview);
25+
26+
const el = await fixture(html`
27+
<mdjs-preview .story=${() => storyHtml`<p id="testing"></p>`}></mdjs-preview>
28+
`);
29+
expect(isCalled).to.be.true;
30+
expect(el.querySelectorAll('#testing').length).to.equal(1);
31+
});
32+
});

packages/mdjs-preview/test-web/mdjs-preview.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import '@mdjs/mdjs-preview/define';
55
/** @typedef {import('@mdjs/mdjs-preview').MdJsPreview} MdJsPreview */
66

77
describe('mdjs-preview', () => {
8-
it('will render the element into the shadow root by default', async () => {
8+
it('will render the element into light dom by default', async () => {
99
const el = await fixture(html`
1010
<mdjs-preview .story=${() => storyHtml`<p id="testing"></p>`}></mdjs-preview>
1111
`);

0 commit comments

Comments
 (0)