Skip to content

Commit af5ccc0

Browse files
authored
Merge pull request #962 from ember-learn/kg-website-redesign
Restore search to the website-redesign branch
2 parents a40cf69 + 31cc450 commit af5ccc0

File tree

77 files changed

+1483
-1289
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+1483
-1289
lines changed

.eslintrc.js

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,24 +13,12 @@ module.exports = {
1313
],
1414
},
1515
},
16-
plugins: ['ember'],
17-
extends: [
18-
'eslint:recommended',
19-
'plugin:ember/recommended',
20-
'plugin:prettier/recommended',
21-
],
16+
extends: ['eslint:recommended'],
2217
env: {
2318
browser: true,
2419
},
2520
rules: {
2621
'no-console': 'off',
27-
'ember/no-new-mixins': 'off',
28-
'ember/no-mixins': 'off',
29-
'ember/require-tagless-components': 'off',
30-
'ember/no-classic-classes': 'off',
31-
'ember/no-get': 'off',
32-
'ember/no-classic-components': 'off',
33-
'ember/no-private-routing-service': 'off',
3422
},
3523
overrides: [
3624
// node files
@@ -62,8 +50,35 @@ module.exports = {
6250
extends: ['plugin:n/recommended'],
6351
},
6452
{
65-
// test files
66-
files: ['tests/**/*-test.{js,ts}'],
53+
files: ['**/*.{js,ts}'],
54+
plugins: ['ember'],
55+
parser: '@typescript-eslint/parser',
56+
extends: [
57+
'eslint:recommended',
58+
'plugin:ember/recommended', // or other configuration
59+
],
60+
rules: {
61+
'ember/no-new-mixins': 'off',
62+
'ember/no-mixins': 'off',
63+
'ember/require-tagless-components': 'off',
64+
'ember/no-classic-classes': 'off',
65+
'ember/no-get': 'off',
66+
'ember/no-classic-components': 'off',
67+
'ember/no-private-routing-service': 'off',
68+
},
69+
},
70+
{
71+
files: ['**/*.gjs'],
72+
parser: 'ember-eslint-parser',
73+
plugins: ['ember'],
74+
extends: [
75+
'eslint:recommended',
76+
'plugin:ember/recommended',
77+
'plugin:ember/recommended-gjs',
78+
],
79+
},
80+
{
81+
files: ['tests/**/*.{js,ts,gjs,gts}'],
6782
extends: ['plugin:qunit/recommended'],
6883
},
6984
],

.github/workflows/gh-pages.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
- uses: pnpm/action-setup@v4
1616
- uses: actions/setup-node@v4
1717
with:
18-
cache: 'pnpm'
18+
cache: "pnpm"
1919
node-version: 20
2020
- run: pnpm i --frozen-lockfile
2121
- 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

.prettierignore

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,15 @@
2323
/package.json.ember-try
2424
/package-lock.json.ember-try
2525
/yarn.lock.ember-try
26+
27+
# Misc files
28+
*.md
29+
pnpm-lock.yaml
30+
jsconfig.json
31+
32+
# api docs data
33+
/ember-api-docs-data/
34+
35+
36+
# hbs -- no point to prettier before moving to <template>
37+
*.hbs

.prettierrc.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
'use strict';
22

33
module.exports = {
4+
plugins: ['prettier-plugin-ember-template-tag'],
45
overrides: [
56
{
6-
files: '*.{js,ts}',
7+
files: '*.{js,ts,gjs,gts}',
78
options: {
89
singleQuote: true,
910
},

.stylelintrc.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
'use strict';
22

33
module.exports = {
4-
extends: ['stylelint-config-standard', 'stylelint-prettier/recommended'],
4+
extends: ['stylelint-config-standard'],
55
};

app.json

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
{
22
"name": "ember-api-docs",
3-
"scripts": {
4-
},
3+
"scripts": {},
54
"env": {
65
"FASTLY_API_KEY": {
76
"required": false
@@ -16,10 +15,8 @@
1615
"required": false
1716
}
1817
},
19-
"formation": {
20-
},
21-
"addons": [
22-
],
18+
"formation": {},
19+
"addons": [],
2320
"buildpacks": [
2421
{
2522
"url": "https://buildpack-registry.s3.amazonaws.com/buildpacks/aedev/emberjs.tgz"

app/adapters/application.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export default class Application extends JSONAPIAdapter {
5656
if (typeof revId !== 'undefined') {
5757
let encodedRevId = encodeURIComponent(revId);
5858
url = `json-docs/${projectName}/${version}/${pluralize(
59-
modelNameToUse
59+
modelNameToUse,
6060
)}/${encodedRevId}`;
6161
} else {
6262
throw new Error('Documentation item not found');
@@ -65,7 +65,7 @@ export default class Application extends JSONAPIAdapter {
6565
let version = this.projectService.version;
6666
let revId = this.metaStore.getRevId(projectName, version, modelName, id);
6767
url = `json-docs/${projectName}/${version}/${pluralize(
68-
modelName
68+
modelName,
6969
)}/${revId}`;
7070
} else if (modelName === 'project') {
7171
this.currentProject = id;
@@ -86,7 +86,7 @@ export default class Application extends JSONAPIAdapter {
8686
let response = await fetch(url);
8787
if (!response.ok) {
8888
throw new Error(
89-
`Network response was not ok: ${response.status} ${response.statusText}`
89+
`Network response was not ok: ${response.status} ${response.statusText}`,
9090
);
9191
}
9292
let json = await response.json();

app/components/api-search.gjs

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
import Component from '@glimmer/component';
2+
import { service } from '@ember/service';
3+
import { LinkTo } from '@ember/routing';
4+
import { array } from '@ember/helper';
5+
import { htmlSafe } from '@ember/template';
6+
import eq from 'ember-truth-helpers/helpers/eq';
7+
import { on } from '@ember/modifier';
8+
import Search from './search';
9+
10+
const SearchResultGroupHeader = <template>
11+
<div class='search-results--group-header' ...attributes>
12+
{{yield}}
13+
</div>
14+
</template>;
15+
16+
const SearchResultLinkContents = <template>
17+
<span class='screen-reader-text'>{{@groupName}}</span>
18+
{{htmlSafe @result._highlightResult.hierarchy.lvl2.value}}
19+
{{! Do these ever display in API Docs? }}
20+
{{#if @result._highlightResult.hierarchy.lvl3}}
21+
<span aria-hidden='true'> › </span>
22+
{{htmlSafe @result._highlightResult.hierarchy.lvl3.value}}
23+
{{/if}}
24+
{{#if @result._highlightResult.hierarchy.lvl4}}
25+
<span aria-hidden='true'> › </span>
26+
{{htmlSafe @result._highlightResult.hierarchy.lvl4.value}}
27+
{{/if}}
28+
</template>;
29+
30+
const SearchResult = class SearchResult extends Component {
31+
@service router;
32+
33+
get module() {
34+
if (this.args.result?.project) {
35+
return this.args.result?.project;
36+
}
37+
let module = this.args.result?.module;
38+
if (module.includes('ember-data')) {
39+
return 'ember-data';
40+
}
41+
return 'ember';
42+
}
43+
44+
get version() {
45+
let versionTag = (this.args.result?._tags ?? []).find(
46+
(_tag) => _tag.indexOf('version:') > -1,
47+
);
48+
let versionSegments = versionTag.replace('version:', '').split('.');
49+
return `${versionSegments[0]}.${versionSegments[1]}`;
50+
}
51+
52+
urlForClass = (result) => {
53+
return `${this.router.urlFor('project-version.classes.class', this.module, this.version, result.class)}#${result.name}`;
54+
};
55+
56+
<template>
57+
<div class='search-results--result'>
58+
<div class='search-results--subcategory-column' aria-hidden='true'>
59+
{{#if (eq @groupPosition 0)}}
60+
{{@groupName}}
61+
{{/if}}
62+
</div>
63+
<div class='search-results--content'>
64+
{{#if @result.static}}
65+
<LinkTo
66+
@route='project-version.functions.function'
67+
@models={{array
68+
this.module
69+
this.version
70+
@result.class
71+
@result.name
72+
}}
73+
{{on 'click' @closeMenu}}
74+
data-test-search-result
75+
>
76+
<SearchResultLinkContents
77+
@result={{@result}}
78+
@groupName={{@groupName}}
79+
/>
80+
</LinkTo>
81+
{{else}}
82+
<a href='{{this.urlForClass @result}}' data-test-search-result>
83+
<SearchResultLinkContents
84+
@result={{@result}}
85+
@groupName={{@groupName}}
86+
/>
87+
</a>
88+
{{/if}}
89+
</div>
90+
</div>
91+
</template>
92+
};
93+
94+
const SearchResults = class SearchBox extends Component {
95+
get groupedResults() {
96+
let results = this.args.results;
97+
if (!results.length) {
98+
return {};
99+
}
100+
101+
const lvl0Group = results.reduce((previous, current) => {
102+
// Remap all lowercase usages of 'guides' to 'Guides'
103+
let lvl0 = current?.hierarchy?.lvl0;
104+
// If lvl0 doesn't exist in the resulting object, create the array
105+
if (!previous[lvl0]) {
106+
previous[lvl0] = [];
107+
}
108+
// Insert the current item into the resulting object.
109+
previous[lvl0].push(current);
110+
return previous;
111+
}, {});
112+
113+
/*
114+
lvl0Group = {
115+
lvl0key: algoliaHit
116+
}
117+
*/
118+
// https://www.algolia.com/doc/guides/building-search-ui/ui-and-ux-patterns/highlighting-snippeting/js/#response-information
119+
// Iterate over every lvl0 group, group by lvl1
120+
return Object.keys(lvl0Group).reduce((lvl0Result, lvl0Key) => {
121+
// Inject lvl1 grouped results into lvl0
122+
lvl0Result[lvl0Key] = lvl0Group[lvl0Key].reduce(
123+
(lvl1Result, lvl1Item) => {
124+
// lvl1 is sometimes null. Normalise to a string.
125+
const lvl1Value = lvl1Item?.hierarchy?.lvl1;
126+
const lvl1Key = lvl1Value ? lvl1Value : lvl0Key;
127+
128+
if (!lvl1Result[lvl1Key]) {
129+
lvl1Result[lvl1Key] = [];
130+
}
131+
132+
lvl1Result[lvl1Key].push(lvl1Item);
133+
return lvl1Result;
134+
},
135+
{},
136+
);
137+
138+
return lvl0Result;
139+
}, {});
140+
}
141+
142+
<template>
143+
{{#each-in this.groupedResults as |lvl0section _lvl0results|}}
144+
<SearchResultGroupHeader aria-hidden='true'>
145+
{{lvl0section}}
146+
</SearchResultGroupHeader>
147+
148+
{{#each-in _lvl0results as |lvl1section _lvl1results|}}
149+
{{#each _lvl1results as |result index|}}
150+
<SearchResult
151+
@result={{result}}
152+
@groupName={{lvl1section}}
153+
@groupPosition={{index}}
154+
@closeMenu={{@closeMenu}}
155+
data-test-search-result
156+
/>
157+
{{/each}}
158+
{{/each-in}}
159+
{{/each-in}}
160+
</template>
161+
};
162+
163+
export default class ApiSearch extends Component {
164+
@service('search') searchService;
165+
@service('project') projectService;
166+
167+
<template>
168+
<Search @searchService={{this.searchService}}>
169+
<:searchInputScreenReaderLabel>Search v{{this.projectService.version}}
170+
of the API Docs. Results will update as you type.</:searchInputScreenReaderLabel>
171+
<:instructions>Type to search v{{this.projectService.version}}
172+
of the API Docs</:instructions>
173+
<:results as |results closeMenu|>
174+
<SearchResults @results={{results}} @closeMenu={{closeMenu}} />
175+
</:results>
176+
</Search>
177+
</template>
178+
}

app/components/class-field-description.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export default class ClassFieldDescription extends Component {
88
get hasImportExample() {
99
return this.legacyModuleMappings.hasFunctionMapping(
1010
this.args.field.name,
11-
this.args.field.class
11+
this.args.field.class,
1212
);
1313
}
1414
}

app/components/search-input.hbs

Lines changed: 0 additions & 33 deletions
This file was deleted.

0 commit comments

Comments
 (0)