Skip to content
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
40 changes: 22 additions & 18 deletions app/components/class-field-description.gjs
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import { service } from '@ember/service';
import Component from '@glimmer/component';
import svgJar from 'ember-svg-jar/helpers/svg-jar';
import { LinkTo } from '@ember/routing';
import { array, concat } from '@ember/helper';
import githubLink from 'ember-api-docs/helpers/github-link';
import and from 'ember-truth-helpers/helpers/and';
import eq from 'ember-api-docs/helpers/eq';
import ImportExample from 'ember-api-docs/components/import-example';
import MarkdownToHtml from 'ember-cli-showdown/components/markdown-to-html';

Expand All @@ -19,6 +16,16 @@ function combineNames(items) {
}

export default class ClassFieldDescription extends Component {
get displayImportExample() {
return (
this.args.field.exampleimport !== undefined ||
(this.args.field.noimport === undefined &&
this.args.field.static === 1 &&
this.args.field.itemtype === 'method' &&
isImportablePackage(this.args.field.class))
);
}

<template>
{{! template-lint-disable no-invalid-interactive }}
<section class="class-field-description {{@type}}">
Expand Down Expand Up @@ -101,16 +108,11 @@ export default class ClassFieldDescription extends Component {
Available since v{{@field.since}}
</p>
{{/if}}
{{#if
(and
(eq @field.static 1)
(eq @field.itemtype "method")
this.hasImportExample
)
}}
{{#if this.displayImportExample}}
<ImportExample
@item={{concat "{ " @field.name " }"}}
@package={{@field.class}}
@exampleimport={{@field.exampleimport}}
/>
{{/if}}
<dl class="parameters">
Expand Down Expand Up @@ -143,13 +145,15 @@ export default class ClassFieldDescription extends Component {
<MarkdownToHtml @markdown={{@field.description}} />
</section>
</template>
@service
legacyModuleMappings;
}

get hasImportExample() {
return this.legacyModuleMappings.hasFunctionMapping(
this.args.field.name,
this.args.field.class,
);
}
function isImportablePackage(packageName) {
/* Broadly define which types of static functions display generated import
examples. This previously relied on `mappings.json` but this meant that newly
added APIs did not display import examples.

This should strike a balance of displaying import examples for new APIs and
not displaying them before the APIs were importable.
*/
return packageName.startsWith('@') || packageName === 'rsvp';
}
11 changes: 8 additions & 3 deletions app/components/import-example.gjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@ import Component from '@glimmer/component';
import MarkdownToHtml from 'ember-cli-showdown/components/markdown-to-html';

export default class ImportExample extends Component {
<template><MarkdownToHtml @markdown={{this.markdown}} /></template>
get markdown() {
let md = `\`\`\`js
if (this.args.exampleimport) {
return `\`\`\`js
${this.args.exampleimport}
\`\`\``;
}
return `\`\`\`js
import ${this.args.item} from '${this.args.package}';
\`\`\``;
return md;
}

<template><MarkdownToHtml @markdown={{this.markdown}} /></template>
}
92 changes: 92 additions & 0 deletions tests/integration/components/class-field-description-test.gjs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,98 @@ module('Integration | Component | class field description', function (hooks) {
assert.dom('[data-test-module]').hasText('@ember/component');
});

test('shows import example for static method on @-scoped package', async function (assert) {
const type = 'method';
const field = {
name: 'hash',
static: 1,
itemtype: 'method',
class: '@ember/helper',
};

await render(
<template>
<ClassFieldDescription @type={{type}} @field={{field}} />
</template>,
);

assert.dom('*').containsText("import { hash } from '@ember/helper';");
});

test('shows import example for static method on rsvp', async function (assert) {
const type = 'method';
const field = {
name: 'all',
static: 1,
itemtype: 'method',
class: 'rsvp',
};

await render(
<template>
<ClassFieldDescription @type={{type}} @field={{field}} />
</template>,
);

assert.dom('*').containsText("import { all } from 'rsvp';");
});

test('does not show import example when noimport flag exists', async function (assert) {
const type = 'method';
const field = {
name: 'hash',
static: 1,
itemtype: 'method',
class: '@ember/helper',
noimport: '',
};

await render(
<template>
<ClassFieldDescription @type={{type}} @field={{field}} />
</template>,
);

assert.dom('pre code').doesNotExist();
});

test('does not show import example for non-importable package', async function (assert) {
const type = 'method';
const field = {
name: 'someMethod',
static: 1,
itemtype: 'method',
class: 'SomeInternalClass',
};

await render(
<template>
<ClassFieldDescription @type={{type}} @field={{field}} />
</template>,
);

assert.dom('pre code').doesNotExist();
});

test('shows import example when field has exampleimport override', async function (assert) {
const type = 'method';
const field = {
name: 'myMethod',
exampleimport: "import { myMethod } from 'some-package/internal';",
class: 'SomeInternalClass',
};

await render(
<template>
<ClassFieldDescription @type={{type}} @field={{field}} />
</template>,
);

assert
.dom('*')
.containsText("import { myMethod } from 'some-package/internal';");
});

test('parameter props are displayed', async function (assert) {
const type = 'method';
const field = {
Expand Down
16 changes: 16 additions & 0 deletions tests/integration/components/import-example-test.gjs
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,20 @@ module('Integration | Component | import example', function (hooks) {
);
assert.dom('*').hasText("import { uniqBy } from '@ember/object/computed';");
});

test('it renders a custom exampleimport override', async function (assert) {
await render(
<template>
{{! template-lint-disable no-potential-path-strings }}
<ImportExample
@item="{ someMethod }"
@package="@ember/utils"
@exampleimport="import { someMethod } from '@ember/utils/legacy';"
/>
</template>,
);
assert
.dom('*')
.hasText("import { someMethod } from '@ember/utils/legacy';");
});
});
Loading