Skip to content

Commit 940e829

Browse files
committed
Auto merge of #3250 - Turbo87:sidebar-links, r=pichfl
CrateHeader: Move quick links into the sidebar I guess a picture is worth a thousand words: ![localhost_4200_crates_rand](https://user-images.githubusercontent.com/141300/107149523-55f41f00-6959-11eb-960f-d30b3d117a96.png) This PR moves the quick links from the crate details header to the sidebar. It also changes their appears a little bit to make it easier to see what link you're clicking on. Instead of just showing e.g. the label "Homepage" we will now also show the actual URL to make it easier for our users to avoid malicious URLs. To make the URLs easier to parse we also add icons for the two more common link types: docs.rs and github.com. We don't plan on adding icons for every single hosting provider available, but for the most mainstream ones it seems useful. In other words: PRs to add e.g. an icon for GitLab would probably be accepted, but a dedicated icon for your own domain that nobody else uses is very unlikely to be accepted. This is opened in draft mode for now since `@pietroalbini` requested to have a look before merging it, but a review (and potentially approval) would still be good. :) Resolves #2520
2 parents 534cee7 + 58e2ea5 commit 940e829

File tree

11 files changed

+188
-49
lines changed

11 files changed

+188
-49
lines changed

app/components/crate-header.hbs

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,4 @@
1212
<FollowButton @crate={{@crate}}/>
1313
{{/if}}
1414
</div>
15-
16-
<ul local-class="quick-links">
17-
{{#if @crate.homepage}}
18-
<li><a href="{{@crate.homepage}}">Homepage</a></li>
19-
{{/if}}
20-
{{#if @crate.wiki}}
21-
<li><a href="{{@crate.wiki}}">Wiki</a></li>
22-
{{/if}}
23-
{{#if @crate.mailing_list}}
24-
<li><a href="{{@crate.mailing_list}}">Mailing list</a></li>
25-
{{/if}}
26-
{{#if this.documentationLink}}
27-
<li><a href="{{this.documentationLink}}" data-test-docs-link>Documentation</a></li>
28-
{{/if}}
29-
{{#if @crate.repository}}
30-
<li><a href="{{@crate.repository}}">Repository</a></li>
31-
{{/if}}
32-
</ul>
3315
</PageHeader>

app/components/crate-header.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,4 @@ import Component from '@glimmer/component';
33

44
export default class CrateHeader extends Component {
55
@service session;
6-
7-
get documentationLink() {
8-
return this.args.version?.documentationLink ?? this.args.crate.documentation;
9-
}
106
}

app/components/crate-header.module.css

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
.header-row {
77
display: flex;
88
justify-content: space-between;
9-
padding-bottom: 10px;
109
}
1110

1211
.heading {
@@ -30,23 +29,3 @@
3029
width: 32px;
3130
height: 32px;
3231
}
33-
34-
.quick-links {
35-
display: flex;
36-
flex-direction: row;
37-
flex-wrap: wrap;
38-
39-
font-size: 80%;
40-
list-style-type: none;
41-
margin: 1em 0 0 0;
42-
padding: 0;
43-
44-
45-
li {
46-
margin-right: 1em;
47-
48-
&:last-child {
49-
margin-right: 0;
50-
}
51-
}
52-
}

app/components/crate-sidebar.hbs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,44 @@
3838
{{/if}}
3939
</div>
4040

41+
<div>
42+
{{#if (and @crate.homepage (not-eq @crate.repository @crate.homepage))}}
43+
<CrateSidebar::Link
44+
@title="Homepage"
45+
@url={{@crate.homepage}}
46+
/>
47+
{{/if}}
48+
49+
{{#if @crate.wiki}}
50+
<CrateSidebar::Link
51+
@title="Wiki"
52+
@url={{@crate.wiki}}
53+
/>
54+
{{/if}}
55+
56+
{{#if @crate.mailing_list}}
57+
<CrateSidebar::Link
58+
@title="Mailing list"
59+
@url={{@crate.mailing_list}}
60+
/>
61+
{{/if}}
62+
63+
{{#if @version.documentationLink}}
64+
<CrateSidebar::Link
65+
@title="Documentation"
66+
@url={{@version.documentationLink}}
67+
data-test-docs-link
68+
/>
69+
{{/if}}
70+
71+
{{#if @crate.repository}}
72+
<CrateSidebar::Link
73+
@title="Repository"
74+
@url={{@crate.repository}}
75+
/>
76+
{{/if}}
77+
</div>
78+
4179
<div>
4280
<h3>Owners</h3>
4381

app/components/crate-sidebar/link.hbs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<div ...attributes>
2+
<h3 data-test-title>{{@title}}</h3>
3+
<div local-class="content">
4+
{{#if this.isDocsRs}}
5+
{{svg-jar "docs-rs" local-class="icon" data-test-icon="docs-rs"}}
6+
{{else if this.isGitHub}}
7+
{{svg-jar "GitHub-Mark" local-class="icon" data-test-icon="github"}}
8+
{{else}}
9+
{{svg-jar "link" local-class="icon" data-test-icon="link"}}
10+
{{/if}}
11+
12+
<a href={{@url}} data-test-link>
13+
{{this.text}}
14+
</a>
15+
</div>
16+
</div>

app/components/crate-sidebar/link.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import Component from '@glimmer/component';
2+
3+
export default class CrateSidebarLink extends Component {
4+
get text() {
5+
let { url } = this.args;
6+
if (url.startsWith('https://')) {
7+
url = url.slice('https://'.length);
8+
}
9+
if (url.startsWith('www.')) {
10+
url = url.slice('www.'.length);
11+
}
12+
13+
return url;
14+
}
15+
16+
get isDocsRs() {
17+
return this.text.startsWith('docs.rs/');
18+
}
19+
20+
get isGitHub() {
21+
return this.text.startsWith('github.com/');
22+
}
23+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
.content {
2+
display: flex;
3+
align-items: center;
4+
}
5+
6+
.icon {
7+
flex-shrink: 0;
8+
height: 1em;
9+
width: auto;
10+
margin-right: 7px;
11+
}

public/assets/docs-rs.svg

Lines changed: 4 additions & 0 deletions
Loading

public/assets/link.svg

Lines changed: 53 additions & 0 deletions
Loading
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { render } from '@ember/test-helpers';
2+
import { module, test } from 'qunit';
3+
4+
import { hbs } from 'ember-cli-htmlbars';
5+
6+
import { setupRenderingTest } from 'cargo/tests/helpers';
7+
8+
module('Component | CrateSidebar::Link', function (hooks) {
9+
setupRenderingTest(hooks);
10+
11+
test('renders title and link', async function (assert) {
12+
await render(hbs`<CrateSidebar::Link @title="Homepage" @url="https://www.rust-lang.org" />`);
13+
assert.dom('[data-test-title]').hasText('Homepage');
14+
assert.dom('[data-test-icon]').exists({ count: 1 }).hasAttribute('data-test-icon', 'link');
15+
assert.dom('[data-test-link]').hasAttribute('href', 'https://www.rust-lang.org').hasText('rust-lang.org');
16+
});
17+
18+
test('renders GitHub icon for GitHub links', async function (assert) {
19+
await render(hbs`<CrateSidebar::Link @url="https://github.com/rust-lang/crates.io" />`);
20+
assert.dom('[data-test-icon]').exists({ count: 1 }).hasAttribute('data-test-icon', 'github');
21+
assert
22+
.dom('[data-test-link]')
23+
.hasAttribute('href', 'https://github.com/rust-lang/crates.io')
24+
.hasText('github.com/rust-lang/crates.io');
25+
});
26+
27+
test('renders docs.rs icon for docs.rs links', async function (assert) {
28+
await render(hbs`<CrateSidebar::Link @url="https://docs.rs/tracing" />`);
29+
assert.dom('[data-test-icon]').exists({ count: 1 }).hasAttribute('data-test-icon', 'docs-rs');
30+
assert.dom('[data-test-link]').hasAttribute('href', 'https://docs.rs/tracing').hasText('docs.rs/tracing');
31+
});
32+
33+
test('does not shorten HTTP links', async function (assert) {
34+
await render(hbs`<CrateSidebar::Link @url="http://www.rust-lang.org" />`);
35+
assert.dom('[data-test-link]').hasAttribute('href', 'http://www.rust-lang.org').hasText('http://www.rust-lang.org');
36+
});
37+
});

tests/routes/crate/version/docs-link-test.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ module('Route | crate.version | docs link', function (hooks) {
1111
this.server.create('version', { crateId: 'foo', num: '1.0.0' });
1212

1313
await visit('/crates/foo');
14-
assert.dom('[data-test-docs-link]').hasAttribute('href', 'https://foo.io/docs');
14+
assert.dom('[data-test-docs-link] a').hasAttribute('href', 'https://foo.io/docs');
1515
});
1616

1717
test('show no docs link if `documentation` is unspecified and there are no related docs.rs builds', async function (assert) {
@@ -21,7 +21,7 @@ module('Route | crate.version | docs link', function (hooks) {
2121
this.server.get('https://docs.rs/crate/:crate/:version/builds.json', []);
2222

2323
await visit('/crates/foo');
24-
assert.dom('[data-test-docs-link]').doesNotExist();
24+
assert.dom('[data-test-docs-link] a').doesNotExist();
2525
});
2626

2727
test('show docs link if `documentation` is unspecified and there are related docs.rs builds', async function (assert) {
@@ -40,7 +40,7 @@ module('Route | crate.version | docs link', function (hooks) {
4040
]);
4141

4242
await visit('/crates/foo');
43-
assert.dom('[data-test-docs-link]').hasAttribute('href', 'https://docs.rs/foo/1.0.0');
43+
assert.dom('[data-test-docs-link] a').hasAttribute('href', 'https://docs.rs/foo/1.0.0');
4444
});
4545

4646
test('show original docs link if `documentation` points to docs.rs and there are no related docs.rs builds', async function (assert) {
@@ -50,7 +50,7 @@ module('Route | crate.version | docs link', function (hooks) {
5050
this.server.get('https://docs.rs/crate/:crate/:version/builds.json', []);
5151

5252
await visit('/crates/foo');
53-
assert.dom('[data-test-docs-link]').hasAttribute('href', 'https://docs.rs/foo/0.6.2');
53+
assert.dom('[data-test-docs-link] a').hasAttribute('href', 'https://docs.rs/foo/0.6.2');
5454
});
5555

5656
test('show updated docs link if `documentation` points to docs.rs and there are related docs.rs builds', async function (assert) {
@@ -69,7 +69,7 @@ module('Route | crate.version | docs link', function (hooks) {
6969
]);
7070

7171
await visit('/crates/foo');
72-
assert.dom('[data-test-docs-link]').hasAttribute('href', 'https://docs.rs/foo/1.0.0');
72+
assert.dom('[data-test-docs-link] a').hasAttribute('href', 'https://docs.rs/foo/1.0.0');
7373
});
7474

7575
test('ajax errors are ignored', async function (assert) {
@@ -79,6 +79,6 @@ module('Route | crate.version | docs link', function (hooks) {
7979
this.server.get('https://docs.rs/crate/:crate/:version/builds.json', {}, 500);
8080

8181
await visit('/crates/foo');
82-
assert.dom('[data-test-docs-link]').hasAttribute('href', 'https://docs.rs/foo/0.6.2');
82+
assert.dom('[data-test-docs-link] a').hasAttribute('href', 'https://docs.rs/foo/0.6.2');
8383
});
8484
});

0 commit comments

Comments
 (0)