Skip to content
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

Provide alternative to inheritance for customizing component paths #88

Merged
merged 1 commit into from
Oct 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 25 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

Provides:

* Component `{{render-mobiledoc}}` for rendering mobiledoc in your ember app
* Component `<RenderMobiledoc ... />` for rendering mobiledoc in your ember app
* (For advanced use) The ability to import the [`mobiledoc-dom-renderer`](https://github.com/bustlelabs/mobiledoc-dom-renderer) class

To learn more about mobiledoc see [mobiledoc-kit](https://github.com/bustlelabs/mobiledoc-kit).
Expand All @@ -23,15 +23,15 @@ To learn more about mobiledoc see [mobiledoc-kit](https://github.com/bustlelabs/
#### Render basic mobiledoc in your template

```hbs
{{render-mobiledoc mobiledoc=myMobileDoc}}
<RenderMmobiledoc @mobiledoc={{myMobileDoc}} />
```

#### Render mobiledoc with cards, using ember components to render cards

```hbs
{{! myMobiledoc is the mobiledoc you want to render }}
{{! myCardNames is an array of card names, e.g. ['embed-card', 'slideshow-card'] }}
{{render-mobiledoc mobiledoc=myMobileDoc cardNames=myCardNames}}
<RenderMmobiledoc @mobiledoc={{myMobileDoc}} @cardNames={{myCardNames}} />
```

The ember components with names matching the mobiledoc card names will be rendered
Expand All @@ -40,19 +40,30 @@ The ember components will be in a wrapper div with the class '__rendered-mobiled

#### Customizing card lookup

If your mobiledoc card names do not match component names, you can subclass
the `render-mobiledoc` component and override its `cardNameToComponentName` method.
If your mobiledoc card names do not match component names, you can pass an argument to
the `<RenderMobiledoc...>` component to provide your own mapping.

E.g.:

```hbs
// components/my-component.hbs
<RenderMobiledoc
@mobiledoc={{...}}
@cardNameToComponentName={{this.cardNameToComponentName}}
/>
```

```javascript
// components/my-render-mobiledoc.js
import RenderMobiledoc from 'ember-mobiledoc-dom-renderer/components/render-mobiledoc';
export default RenderMobiledoc.extend({
// components/my-component.js
import Component from '@glimmer/component';
import { action } from '@ember/object';

export default class extends Component {
@action
cardNameToComponentName(mobiledocCardName) {
return 'cards/' + mobiledocCardName;
}
});
}
```

#### Render mobiledoc with atoms, using ember components to render atoms
Expand All @@ -61,13 +72,13 @@ This works the same way as rendering mobiledoc with ember components for cards.
To pass atom names to the renderer, use the `atomNames` property, e.g.:
```hbs
{{! myAtomNames is an array of atom names, e.g. ['mention-atom'] }}
{{render-mobiledoc mobiledoc=myMobileDoc atomNames=myAtomNames}}
<RenderMobiledoc @mobiledoc={{myMobileDoc}} @atomNames={{myAtomNames}} />
```

The component will be passed a `payload` and `value` property.

To customize atom lookup, extend the `render-mobiledoc` component and override
its `atomNameToComponentName` method.
To customize atom lookup, pass an `atomNameToComponentName` argument similar to
what is shown above for `cardNameToComponentName`.

#### Customizing markup and section rendering
The `sectionElementRenderer` and `markupElementRenderer` options can be used to
Expand All @@ -76,7 +87,7 @@ customize the elements used for sections and inline text decorations respectivel
E.g.:

```hbs
{{render-mobiledoc mobiledoc=myMobileDoc sectionElementRenderer=mySectionElementRenderer}}
<RenderMobiledoc @mobiledoc={{this.myMobileDoc}} @sectionElementRenderer={{this.mySectionElementRenderer}} />
```

```js
Expand All @@ -92,7 +103,7 @@ mySectionElementRenderer: {
#### Use mobiledoc-dom-renderer directly

This addon provides the mobiledoc-dom-renderer directly. Most of the time
you will want to use the `{{render-mobiledoc}}` component, but if you need
you will want to use the `<RenderMobiledoc />` component, but if you need
to use the renderer directly in code, it can be imported:

`import DOMRenderer from 'ember-mobiledoc-dom-renderer'`;
Expand Down
10 changes: 8 additions & 2 deletions addon/components/render-mobiledoc/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,13 +192,19 @@ export default class extends Component {
return super.willDestroy(...arguments);
}

// override in subclass to change the mapping of card name -> component name
// pass the argument to change the mapping of card name -> component name
cardNameToComponentName(name) {
if (this.args.cardNameToComponentName) {
return this.args.cardNameToComponentName(name);
}
return name;
}

// override in subclass to change the mapping of atom name -> component name
// pass the argument to change the mapping of atom name -> component name
atomNameToComponentName(name) {
if (this.args.atomNameToComponentName) {
return this.args.atomNameToComponentName(name);
}
return name;
}

Expand Down
43 changes: 41 additions & 2 deletions tests/integration/components/render-mobiledoc-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ module('Integration | Component | render-mobiledoc', function (hooks) {
.exists(`renders card with class ${CARD_ELEMENT_CLASS}-${cardName}`);
});

test('it uses `cardNameToComponentName` to allow selecting components', async function (assert) {
test('it uses `cardNameToComponentName` to allow selecting components (inheritance)', async function (assert) {
this.set('mobiledoc', createMobiledocWithCard(cardName));
this.set('cardNames', [cardName]);

Expand All @@ -62,6 +62,24 @@ module('Integration | Component | render-mobiledoc', function (hooks) {
.hasText('foo: bar', 'renders card payload');
});

test('it uses `cardNameToComponentName` to allow selecting components (arg)', async function (assert) {
this.set('mobiledoc', createMobiledocWithCard(cardName));
this.set('cardNames', [cardName]);
this.set('cardNameToComponentName', (cardName) => {
return cardName.replace('sample', 'sample-changed-name');
});
await render(
hbs`<RenderMobiledoc @mobiledoc={{this.mobiledoc}} @cardNames={{this.cardNames}} @cardNameToComponentName={{this.cardNameToComponentName}} />`
);
assert.dom('#sample-test-card').doesNotExist();
assert
.dom('#sample-changed-name-test-card')
.exists('renders card template');
assert
.dom('#sample-changed-name-test-card')
.hasText('foo: bar', 'renders card payload');
});

test('it renders mobiledoc with atoms', async function (assert) {
this.set('mobiledoc', createMobiledocWithAtom(atomName));
this.set('atomNames', [atomName]);
Expand All @@ -84,7 +102,7 @@ module('Integration | Component | render-mobiledoc', function (hooks) {
.exists(`renders atom with class ${ATOM_ELEMENT_CLASS}-${atomName}`);
});

test('it uses `atomNameToComponentName` to allow selecting components', async function (assert) {
test('it uses `atomNameToComponentName` to allow selecting components (inheritance)', async function (assert) {
this.set('mobiledoc', createMobiledocWithAtom(atomName));
this.set('atomNames', [atomName]);

Expand All @@ -105,6 +123,27 @@ module('Integration | Component | render-mobiledoc', function (hooks) {
.includesText('payload: bar', 'renders atom payload');
});

test('it uses `atomNameToComponentName` to allow selecting components (arg)', async function (assert) {
this.set('mobiledoc', createMobiledocWithAtom(atomName));
this.set('atomNames', [atomName]);
this.set('atomNameToComponentName', (atomName) => {
return atomName.replace('sample', 'sample-changed-name');
});
await render(
hbs`<RenderMobiledoc @mobiledoc={{this.mobiledoc}} @atomNames={{this.atomNames}} @atomNameToComponentName={{this.atomNameToComponentName}} />`
);
assert.dom('#sample-test-atom').doesNotExist();
assert
.dom('#sample-changed-name-test-atom')
.exists('renders atom template');
assert
.dom('#sample-changed-name-test-atom')
.includesText('value: value', 'renders atom value');
assert
.dom('#sample-changed-name-test-atom')
.includesText('payload: bar', 'renders atom payload');
});

test("it does not rerender if a atom component changes its card's payload or value", async function (assert) {
let inserted = 0;
let atom;
Expand Down