Skip to content

Commit 4012b53

Browse files
committed
Add frontend linecount display
This implements linecount display in the crate sidebar by adding a `linecounts` attribute to the `Version` Ember Data model and displaying total code lines alongside existing crate size information. A code icon is included for visual consistency with other metrics. The implementation handles `null` linecount data gracefully for backward compatibility.
1 parent 833c90f commit 4012b53

File tree

6 files changed

+51
-1
lines changed

6 files changed

+51
-1
lines changed

app/components/crate-sidebar.css

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
.msrv,
2323
.edition,
2424
.license,
25+
.linecount,
2526
.bytes,
2627
.purl {
2728
display: flex;
@@ -37,7 +38,8 @@
3738

3839
.date,
3940
.msrv,
40-
.edition {
41+
.edition,
42+
.linecount {
4143
> span {
4244
cursor: help;
4345
}
@@ -49,6 +51,7 @@
4951
}
5052
}
5153

54+
.linecount,
5255
.bytes {
5356
font-variant-numeric: tabular-nums;
5457
}

app/components/crate-sidebar.gjs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import Tooltip from 'crates-io/components/tooltip';
2121
import dateFormat from 'crates-io/helpers/date-format';
2222
import dateFormatDistanceToNow from 'crates-io/helpers/date-format-distance-to-now';
2323
import dateFormatIso from 'crates-io/helpers/date-format-iso';
24+
import formatShortNum from 'crates-io/helpers/format-short-num';
2425
import prettyBytes from 'crates-io/helpers/pretty-bytes';
2526

2627
import { simplifyUrl } from './crate-sidebar/link';
@@ -125,6 +126,20 @@ export default class CrateSidebar extends Component {
125126
</div>
126127
{{/if}}
127128

129+
{{#if @version.linecounts.total_code_lines}}
130+
<div class='linecount' data-test-linecounts>
131+
{{svgJar 'code'}}
132+
<span>
133+
{{formatShortNum @version.linecounts.total_code_lines}}
134+
SLoC
135+
<Tooltip>
136+
Source Lines of Code<br />
137+
<small>(excluding comments, integration tests and example code)</small>
138+
</Tooltip>
139+
</span>
140+
</div>
141+
{{/if}}
142+
128143
{{#if @version.crate_size}}
129144
<div class='bytes'>
130145
{{svgJar 'weight'}}

app/models/version.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export default class Version extends Model {
2525
@attr yanked;
2626
@attr license;
2727
@attr crate_size;
28+
@attr linecounts;
2829

2930
/**
3031
* The minimum supported Rust version of this crate version.

e2e/acceptance/crate.spec.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,18 @@ test.describe('Acceptance | crate page', { tag: '@acceptance' }, () => {
210210
await expect(page.locator('[data-test-license]')).toHaveText('MIT OR Apache-2.0');
211211
});
212212

213+
test('sidebar shows correct information', async ({ page, msw }) => {
214+
let crate = msw.db.crate.create({ name: 'foo' });
215+
msw.db.version.create({ crate, num: '0.5.0' });
216+
msw.db.version.create({ crate, num: '1.0.0' });
217+
218+
await page.goto('/crates/foo');
219+
await expect(page.locator('[data-test-linecounts]')).toHaveText('1,119 SLoC');
220+
221+
await page.goto('/crates/foo/0.5.0');
222+
await expect(page.locator('[data-test-linecounts]')).toHaveText('520 SLoC');
223+
});
224+
213225
test.skip('crates can be yanked by owner', async ({ page, msw }) => {
214226
loadFixtures(msw.db);
215227

public/assets/code.svg

Lines changed: 5 additions & 0 deletions
Loading

tests/acceptance/crate-test.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,4 +306,18 @@ module('Acceptance | crate page', function (hooks) {
306306
assert.strictEqual(currentURL(), '/crates/nanomsg');
307307
assert.dom('[data-test-keyword]').exists();
308308
});
309+
310+
test('sidebar shows correct information', async function (assert) {
311+
this.owner.lookup('service:intl').locale = 'en';
312+
313+
let crate = this.db.crate.create({ name: 'foo' });
314+
this.db.version.create({ crate, num: '0.5.0' });
315+
this.db.version.create({ crate, num: '1.0.0' });
316+
317+
await visit('/crates/foo');
318+
assert.dom('[data-test-linecounts]').hasText('1,119 SLoC');
319+
320+
await visit('/crates/foo/0.5.0');
321+
assert.dom('[data-test-linecounts]').hasText('520 SLoC');
322+
});
309323
});

0 commit comments

Comments
 (0)