@bongos/core 1.23.9 → 1.23.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/.bongos-core.json +106 -41
  2. package/docs/adr/0337-the-hub-account-is-the-person-a-hall-account-is-their-seat-in-one-project.md +1 -0
  3. package/docs/copy-inventory.md +900 -725
  4. package/docs/copy-registry.json +3055 -1246
  5. package/docs/file-map.md +1 -0
  6. package/docs/module-api-changelog.md +4 -0
  7. package/docs/page-inventory.json +49 -6
  8. package/docs/page-readings.json +1247 -1157
  9. package/modules/public-landing/public/account.html +12 -0
  10. package/modules/public-landing/public/assets/cosmos.css +9 -1
  11. package/modules/public-landing/public/assets/hub-bar.js +5 -3
  12. package/modules/public-landing/public/community-empty.states.json +15 -0
  13. package/modules/public-landing/public/community-recruiter.states.json +15 -0
  14. package/modules/public-landing/public/community.html +470 -0
  15. package/modules/public-landing/public/community.probes.json +92 -0
  16. package/modules/public-landing/public/community.states.json +25 -0
  17. package/modules/public-landing/public/connections-nosuggest.states.json +15 -0
  18. package/modules/public-landing/public/connections.html +33 -2
  19. package/modules/public-landing/public/connections.states.json +1 -0
  20. package/modules/public-landing/public/contact.html +12 -0
  21. package/modules/public-landing/public/guild.html +12 -0
  22. package/modules/public-landing/public/index.html +23 -2
  23. package/modules/public-landing/public/index.probes.json +1 -1
  24. package/modules/public-landing/public/invitations.html +12 -0
  25. package/modules/public-landing/public/privacy.html +12 -0
  26. package/modules/public-landing/public/projects.html +15 -1
  27. package/modules/public-landing/public/terms.html +12 -0
  28. package/modules/ui-design/kit/fixtures/community-leaderboard-empty.json +4 -0
  29. package/modules/ui-design/kit/fixtures/community-leaderboard.json +28 -0
  30. package/modules/ui-design/kit/fixtures/community-search.json +10 -0
  31. package/modules/ui-design/kit/fixtures/connections-nosuggest.json +12 -0
  32. package/modules/ui-design/kit/fixtures/scouting-recruiter.json +11 -0
  33. package/modules/ui-design/kit/fixtures/scouting.json +4 -0
  34. package/modules/ui-design/kit/serve.js +55 -0
  35. package/package-lock.json +2 -2
  36. package/package.json +1 -1
  37. package/release-notes.json +12 -0
  38. package/src/bongos/serve-internal.js +4 -2
  39. package/src/module-api.js +1 -1
  40. package/src/platform-server.js +11 -0
  41. package/tests/hub_account_page.mjs +9 -1
  42. package/tests/hub_community_page.mjs +493 -0
  43. package/tests/hub_connections_page.mjs +53 -4
  44. package/tests/hub_guild_page.mjs +1 -0
  45. package/tests/landing_legal_pages.mjs +10 -1
  46. package/tests/landing_page.mjs +1 -1
  47. package/tests/render_check.mjs +2 -2
  48. package/tests/ui_design_kit.mjs +2 -2
@@ -193,7 +193,11 @@ for (const p of PAGES) {
193
193
  assert.deepEqual(bandLinks(bandOf(html, 'menuProjects')), [
194
194
  ['Sky', '/projects?view=map'], ['Table', '/projects?view=map&sub=table'],
195
195
  ['Your projects', '/projects?view=mine'], ['New project', '/projects?view=new'],
196
+ // the Community menu's three sub-pages, folded into the band under 480px (task 1003363); apex-only
197
+ ['Leaderboard', '/community'], ['Find a builder', '/community/find'], ['Open to recruiters', '/community/recruiters'],
198
+ ['Builders you may know', '/connections#connSuggest'],
196
199
  ], 'this page has no views of its own, so every item names /projects in full');
200
+ assert.deepEqual(bandLinks(bandOf(stripApexOnly(html, false), 'menuProjects')).map((l) => l[0]), ['Sky', 'Table', 'Your projects', 'New project'], 'a child has no /community');
197
201
  assert.deepEqual(bandLinks(bandOf(html, 'menuProfile')), [
198
202
  ['My projects', '/projects?view=mine'], ['Invitations', '/invitations'], ['Connections', '/connections'], ['Account', '/account'], ['Sign out', '/api/bongos/auth/logout'],
199
203
  ]);
@@ -261,6 +265,8 @@ function bootBar(html, answer, pathname) {
261
265
  els.set(m[3], el(m[3], /\shidden\b/.test(m[2] + m[4]), attrs));
262
266
  }
263
267
  const trigs = [...els.values()].filter((e) => /\btrig\b/.test(e.attrs.class || ''));
268
+ // the signed-in-only "Builders you may know" cells (task 1004256), by class; a child has none
269
+ const knowCells = [...html.matchAll(/<li class="bandCell(?: bandFold)? knowCell" hidden>/g)].map(() => ({ hidden: true }));
264
270
  const bands = [...html.matchAll(/<div class="menuBand" id="(\w+)"[\s\S]*?\n<\/div>/g)].map((m) => {
265
271
  const band = els.get(m[1]);
266
272
  band.items = [...m[0].matchAll(/<li class="bandCell"(?: id="(\w+)")?><a class="([^"]+)" href="([^"]+)"([^>]*)>([^<]+)<\/a>/g)].map((a) => ({
@@ -284,7 +290,7 @@ function bootBar(html, answer, pathname) {
284
290
  const event = (extra) => ({ prevented: false, preventDefault() { this.prevented = true; }, ...extra });
285
291
  const calls = [];
286
292
  const dom = {
287
- els, calls, assigned: null,
293
+ els, calls, knowCells, assigned: null,
288
294
  active: () => document.activeElement,
289
295
  band: (id) => els.get(id),
290
296
  item: (id, text) => els.get(id).items.find((i) => i.text === text),
@@ -309,6 +315,7 @@ function bootBar(html, answer, pathname) {
309
315
  querySelectorAll(sel) {
310
316
  if (sel === '.trig') return trigs;
311
317
  if (sel === '.menuBand') return bands;
318
+ if (sel === '.knowCell') return knowCells;
312
319
  throw new Error(`unstubbed selector: ${sel}`);
313
320
  },
314
321
  };
@@ -338,6 +345,7 @@ for (const p of PAGES) {
338
345
  assert.equal(out.els.get('who').hidden, true, 'no chip without a session');
339
346
  assert.equal(out.els.get('signinTop').hidden, false);
340
347
  assert.equal(out.els.get('mineCell').hidden, true, 'and the Projects band offers no Your projects');
348
+ assert.deepEqual(out.knowCells.map((c) => c.hidden), hub ? [true, true] : [], 'nor Builders you may know; a child has no community menu at all');
341
349
  assert.equal(await out.window.HubBar.ready, null);
342
350
 
343
351
  const dom = bootBar(served, signedIn, p.route);
@@ -349,6 +357,7 @@ for (const p of PAGES) {
349
357
  assert.equal(dom.els.get('who').getAttribute('aria-label'), 'Account, octocat');
350
358
  for (const id of ['whoImg', 'bandWhoImg']) assert.equal(dom.els.get(id).src, 'https://avatars.example/u/1');
351
359
  assert.equal(dom.els.get('mineCell').hidden, false);
360
+ assert.deepEqual(dom.knowCells.map((c) => c.hidden), hub ? [false, false] : []);
352
361
  assert.deepEqual(dom.band('menuProfile').items.map((i) => i.text), hub ? ['My projects', 'Invitations', 'Connections', 'Account', 'Sign out'] : ['My projects', 'Sign out']);
353
362
  });
354
363
  }
@@ -594,7 +594,7 @@ test('the bands are one disclosure: Escape returns focus, arrows cycle, Tab out
594
594
  assert.match(CODE, /else openMenu\(t, ev\.detail === 0\);/, 'a keyboard-fired click is told apart from a pointer');
595
595
  assert.match(CODE, /if \(ev\.key === 'Escape'\) \{ closeMenus\(\); return; \}/);
596
596
  assert.match(CODE, /if \(ev\.key !== 'ArrowDown' && ev\.key !== 'ArrowUp'\) return;/);
597
- assert.match(CODE, /return !a\.closest\('\[hidden\]'\);/, 'the arrows skip the hidden Your-projects cell');
597
+ assert.match(CODE, /return !a\.closest\('\[hidden\]'\) && a\.offsetParent !== null;/, 'the arrows skip the hidden Your-projects cell, and the Community cell above 900px, which CSS does not draw (task 1003363)');
598
598
  assert.match(CODE, /b\.addEventListener\('focusout', function \(ev\) \{[\s\S]*?if \(!to \|\| b\.contains\(to\) \|\| \(to\.closest && to\.closest\('\.trig'\)\)\) return;[\s\S]*?closeMenus\(\);/, 'Tab out closes; a null relatedTarget is left alone');
599
599
  assert.match(CODE, /if \(ev\.target\.closest && \(ev\.target\.closest\('\.menuBand'\) \|\| ev\.target\.closest\('\.trig'\)\)\) return;[\s\S]*?closeMenus\(\);/, 'a click outside closes');
600
600
  assert.doesNotMatch(HTML, /role="menu"|aria-haspopup/, 'plain links in a disclosure — what is announced is what ships');
@@ -25,8 +25,8 @@ test('a shared asset reaches every page in its dir whose HTML names it', () => {
25
25
  assert.deepEqual(names(['modules/hall-ui/public/sky-data.js']), ['goal-map.states.json', 'thinking.states.json']);
26
26
  assert.deepEqual(names(['modules/hall-ui/public/text-fit.js']), ['goals.states.json']);
27
27
  // the account page links the hub's sheet too since task 1004259, the guild page since task 1002301,
28
- // the invitations page since task 1004276, and the connections page since task 1004278
29
- assert.deepEqual(names(['modules/public-landing/public/assets/cosmos.css']), ['account.states.json', 'connections.states.json', 'guild.states.json', 'invitations.states.json', 'projects.states.json']);
28
+ // the invitations page since task 1004276, the connections page since task 1004278, and the community page since task 1003363
29
+ assert.deepEqual(names(['modules/public-landing/public/assets/cosmos.css']), ['account.states.json', 'community.states.json', 'connections.states.json', 'guild.states.json', 'invitations.states.json', 'projects.states.json']);
30
30
  });
31
31
 
32
32
  test('the page a builder changed comes before the pages a shared file reaches, so the render cap never drops it', () => {
@@ -43,14 +43,14 @@ test('the shipped states files validate and sit beside the page they name', () =
43
43
  }
44
44
  // the apex is dark only (task 1003336): its states files name the one mode, and
45
45
  // render.js reads it as the default so a plain `--page /` never renders light
46
- for (const rel of ['modules/public-landing/public/projects.states.json', 'modules/public-landing/public/index.states.json', 'modules/public-landing/public/account.states.json', 'modules/public-landing/public/guild.states.json', 'modules/public-landing/public/invitations.states.json', 'modules/public-landing/public/connections.states.json', 'modules/public-landing/public/connections-empty.states.json', 'modules/public-landing/public/connections-inactive.states.json']) {
46
+ for (const rel of ['modules/public-landing/public/projects.states.json', 'modules/public-landing/public/index.states.json', 'modules/public-landing/public/account.states.json', 'modules/public-landing/public/guild.states.json', 'modules/public-landing/public/invitations.states.json', 'modules/public-landing/public/connections.states.json', 'modules/public-landing/public/connections-empty.states.json', 'modules/public-landing/public/connections-inactive.states.json', 'modules/public-landing/public/community.states.json', 'modules/public-landing/public/community-empty.states.json', 'modules/public-landing/public/community-recruiter.states.json']) {
47
47
  assert.deepEqual(readJson(rel).modes, ['dark'], `${rel}: the apex renders dark only`);
48
48
  assert.equal(readJson(rel).modeQuery, false, `${rel}: no query walks a second mode`);
49
49
  }
50
50
  });
51
51
 
52
52
  test('the shipped probes files validate', () => {
53
- for (const rel of ['modules/public-landing/public/projects.probes.json', 'modules/public-landing/public/index.probes.json', 'modules/public-landing/public/account.probes.json', 'modules/public-landing/public/guild.probes.json', 'modules/public-landing/public/invitations.probes.json', 'modules/public-landing/public/connections.probes.json']) {
53
+ for (const rel of ['modules/public-landing/public/projects.probes.json', 'modules/public-landing/public/index.probes.json', 'modules/public-landing/public/account.probes.json', 'modules/public-landing/public/guild.probes.json', 'modules/public-landing/public/invitations.probes.json', 'modules/public-landing/public/connections.probes.json', 'modules/public-landing/public/community.probes.json']) {
54
54
  const v = lib.validateProbesFile(readJson(rel));
55
55
  assert.deepEqual(v.errors, [], `${rel}: ${v.errors.join('; ')}`);
56
56
  }