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
45 changes: 30 additions & 15 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,12 @@ module.exports = {
],
},
},
plugins: ['ember'],
extends: [
'eslint:recommended',
'plugin:ember/recommended',
'plugin:prettier/recommended',
],
extends: ['eslint:recommended'],
env: {
browser: true,
},
rules: {
'no-console': 'off',
'ember/no-new-mixins': 'off',
'ember/no-mixins': 'off',
'ember/require-tagless-components': 'off',
'ember/no-classic-classes': 'off',
'ember/no-get': 'off',
'ember/no-classic-components': 'off',
'ember/no-private-routing-service': 'off',
},
overrides: [
// node files
Expand Down Expand Up @@ -62,8 +50,35 @@ module.exports = {
extends: ['plugin:n/recommended'],
},
{
// test files
files: ['tests/**/*-test.{js,ts}'],
files: ['**/*.{js,ts}'],
plugins: ['ember'],
parser: '@typescript-eslint/parser',
extends: [
'eslint:recommended',
'plugin:ember/recommended', // or other configuration
],
rules: {
'ember/no-new-mixins': 'off',
'ember/no-mixins': 'off',
'ember/require-tagless-components': 'off',
'ember/no-classic-classes': 'off',
'ember/no-get': 'off',
'ember/no-classic-components': 'off',
'ember/no-private-routing-service': 'off',
},
},
{
files: ['**/*.gjs'],
parser: 'ember-eslint-parser',
plugins: ['ember'],
extends: [
'eslint:recommended',
'plugin:ember/recommended',
'plugin:ember/recommended-gjs',
],
},
{
files: ['tests/**/*.{js,ts,gjs,gts}'],
extends: ['plugin:qunit/recommended'],
},
],
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/gh-pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
cache: 'pnpm'
cache: "pnpm"
node-version: 20
- run: pnpm i --frozen-lockfile
- run: npx lint-to-the-future output -o lttfOutput --rootUrl ember-api-docs --previous-results https://ember-learn.github.io/ember-api-docs/data.json
Expand Down
12 changes: 12 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,15 @@
/package.json.ember-try
/package-lock.json.ember-try
/yarn.lock.ember-try

# Misc files
*.md
pnpm-lock.yaml
jsconfig.json

# api docs data
/ember-api-docs-data/


# hbs -- no point to prettier before moving to <template>
*.hbs
3 changes: 2 additions & 1 deletion .prettierrc.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
'use strict';

module.exports = {
plugins: ['prettier-plugin-ember-template-tag'],
overrides: [
{
files: '*.{js,ts}',
files: '*.{js,ts,gjs,gts}',
options: {
singleQuote: true,
},
Expand Down
2 changes: 1 addition & 1 deletion .stylelintrc.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
'use strict';

module.exports = {
extends: ['stylelint-config-standard', 'stylelint-prettier/recommended'],
extends: ['stylelint-config-standard'],
};
9 changes: 3 additions & 6 deletions app.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"name": "ember-api-docs",
"scripts": {
},
"scripts": {},
"env": {
"FASTLY_API_KEY": {
"required": false
Expand All @@ -16,10 +15,8 @@
"required": false
}
},
"formation": {
},
"addons": [
],
"formation": {},
"addons": [],
"buildpacks": [
{
"url": "https://buildpack-registry.s3.amazonaws.com/buildpacks/aedev/emberjs.tgz"
Expand Down
6 changes: 3 additions & 3 deletions app/adapters/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export default class Application extends JSONAPIAdapter {
if (typeof revId !== 'undefined') {
let encodedRevId = encodeURIComponent(revId);
url = `json-docs/${projectName}/${version}/${pluralize(
modelNameToUse
modelNameToUse,
)}/${encodedRevId}`;
} else {
throw new Error('Documentation item not found');
Expand All @@ -65,7 +65,7 @@ export default class Application extends JSONAPIAdapter {
let version = this.projectService.version;
let revId = this.metaStore.getRevId(projectName, version, modelName, id);
url = `json-docs/${projectName}/${version}/${pluralize(
modelName
modelName,
)}/${revId}`;
} else if (modelName === 'project') {
this.currentProject = id;
Expand All @@ -86,7 +86,7 @@ export default class Application extends JSONAPIAdapter {
let response = await fetch(url);
if (!response.ok) {
throw new Error(
`Network response was not ok: ${response.status} ${response.statusText}`
`Network response was not ok: ${response.status} ${response.statusText}`,
);
}
let json = await response.json();
Expand Down
178 changes: 178 additions & 0 deletions app/components/api-search.gjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
import Component from '@glimmer/component';
import { service } from '@ember/service';
import { LinkTo } from '@ember/routing';
import { array } from '@ember/helper';
import { htmlSafe } from '@ember/template';
import eq from 'ember-truth-helpers/helpers/eq';
import { on } from '@ember/modifier';
import Search from './search';

const SearchResultGroupHeader = <template>
<div class='search-results--group-header' ...attributes>
{{yield}}
</div>
</template>;

const SearchResultLinkContents = <template>
<span class='screen-reader-text'>{{@groupName}}</span>
{{htmlSafe @result._highlightResult.hierarchy.lvl2.value}}
{{! Do these ever display in API Docs? }}
{{#if @result._highlightResult.hierarchy.lvl3}}
<span aria-hidden='true'> › </span>
{{htmlSafe @result._highlightResult.hierarchy.lvl3.value}}
{{/if}}
{{#if @result._highlightResult.hierarchy.lvl4}}
<span aria-hidden='true'> › </span>
{{htmlSafe @result._highlightResult.hierarchy.lvl4.value}}
{{/if}}
</template>;

const SearchResult = class SearchResult extends Component {
@service router;

get module() {
if (this.args.result?.project) {
return this.args.result?.project;
}
let module = this.args.result?.module;
if (module.includes('ember-data')) {
return 'ember-data';
}
return 'ember';
}

get version() {
let versionTag = (this.args.result?._tags ?? []).find(
(_tag) => _tag.indexOf('version:') > -1,
);
let versionSegments = versionTag.replace('version:', '').split('.');
return `${versionSegments[0]}.${versionSegments[1]}`;
}

urlForClass = (result) => {
return `${this.router.urlFor('project-version.classes.class', this.module, this.version, result.class)}#${result.name}`;
};

<template>
<div class='search-results--result'>
<div class='search-results--subcategory-column' aria-hidden='true'>
{{#if (eq @groupPosition 0)}}
{{@groupName}}
{{/if}}
</div>
<div class='search-results--content'>
{{#if @result.static}}
<LinkTo
@route='project-version.functions.function'
@models={{array
this.module
this.version
@result.class
@result.name
}}
{{on 'click' @closeMenu}}
data-test-search-result
>
<SearchResultLinkContents
@result={{@result}}
@groupName={{@groupName}}
/>
</LinkTo>
{{else}}
<a href='{{this.urlForClass @result}}' data-test-search-result>
<SearchResultLinkContents
@result={{@result}}
@groupName={{@groupName}}
/>
</a>
{{/if}}
</div>
</div>
</template>
};

const SearchResults = class SearchBox extends Component {
get groupedResults() {
let results = this.args.results;
if (!results.length) {
return {};
}

const lvl0Group = results.reduce((previous, current) => {
// Remap all lowercase usages of 'guides' to 'Guides'
let lvl0 = current?.hierarchy?.lvl0;
// If lvl0 doesn't exist in the resulting object, create the array
if (!previous[lvl0]) {
previous[lvl0] = [];
}
// Insert the current item into the resulting object.
previous[lvl0].push(current);
return previous;
}, {});

/*
lvl0Group = {
lvl0key: algoliaHit
}
*/
// https://www.algolia.com/doc/guides/building-search-ui/ui-and-ux-patterns/highlighting-snippeting/js/#response-information
// Iterate over every lvl0 group, group by lvl1
return Object.keys(lvl0Group).reduce((lvl0Result, lvl0Key) => {
// Inject lvl1 grouped results into lvl0
lvl0Result[lvl0Key] = lvl0Group[lvl0Key].reduce(
(lvl1Result, lvl1Item) => {
// lvl1 is sometimes null. Normalise to a string.
const lvl1Value = lvl1Item?.hierarchy?.lvl1;
const lvl1Key = lvl1Value ? lvl1Value : lvl0Key;

if (!lvl1Result[lvl1Key]) {
lvl1Result[lvl1Key] = [];
}

lvl1Result[lvl1Key].push(lvl1Item);
return lvl1Result;
},
{},
);

return lvl0Result;
}, {});
}

<template>
{{#each-in this.groupedResults as |lvl0section _lvl0results|}}
<SearchResultGroupHeader aria-hidden='true'>
{{lvl0section}}
</SearchResultGroupHeader>

{{#each-in _lvl0results as |lvl1section _lvl1results|}}
{{#each _lvl1results as |result index|}}
<SearchResult
@result={{result}}
@groupName={{lvl1section}}
@groupPosition={{index}}
@closeMenu={{@closeMenu}}
data-test-search-result
/>
{{/each}}
{{/each-in}}
{{/each-in}}
</template>
};

export default class ApiSearch extends Component {
@service('search') searchService;
@service('project') projectService;

<template>
<Search @searchService={{this.searchService}}>
<:searchInputScreenReaderLabel>Search v{{this.projectService.version}}
of the API Docs. Results will update as you type.</:searchInputScreenReaderLabel>
<:instructions>Type to search v{{this.projectService.version}}
of the API Docs</:instructions>
<:results as |results closeMenu|>
<SearchResults @results={{results}} @closeMenu={{closeMenu}} />
</:results>
</Search>
</template>
}
2 changes: 1 addition & 1 deletion app/components/class-field-description.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default class ClassFieldDescription extends Component {
get hasImportExample() {
return this.legacyModuleMappings.hasFunctionMapping(
this.args.field.name,
this.args.field.class
this.args.field.class,
);
}
}
33 changes: 0 additions & 33 deletions app/components/search-input.hbs

This file was deleted.

Loading