@morphemecms/cms 0.14.2 → 0.14.3-next-20261107160925
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.
- package/CHANGELOG.md +9 -0
- package/lib/license-texts/Unsplash.txt +7 -0
- package/lib/licenses.d.mts +8 -0
- package/lib/licenses.editions.test.mjs +45 -0
- package/lib/licenses.mjs +40 -0
- package/lib/releaseNotes.d.mts +79 -9
- package/lib/releaseNotes.mjs +136 -21
- package/lib/releaseNotes.test.mjs +187 -5
- package/package.json +1 -1
- package/release-notes/editions/0.14.json +12 -0
- package/release-notes/editions/0.14.webp +0 -0
- package/release-notes/i18n/da-DK/0.14.0.json +12 -11
- package/release-notes/i18n/da-DK/0.14.1.json +3 -2
- package/release-notes/i18n/da-DK/0.14.2.json +5 -4
- package/release-notes/i18n/da-DK/pending/edition-photo-card.json +6 -0
- package/release-notes/i18n/da-DK/pending/edition-photo-card.webp +0 -0
- package/release-notes/i18n/da-DK/pending/short-notification-buttons.json +1 -0
- package/release-notes/i18n/da-DK/pending/version-heading-date-photo.json +5 -0
- package/release-notes/i18n/en-US/0.14.0.json +13 -12
- package/release-notes/i18n/en-US/0.14.1.json +3 -2
- package/release-notes/i18n/en-US/0.14.2.json +5 -4
- package/release-notes/i18n/en-US/pending/edition-photo-card.json +6 -0
- package/release-notes/i18n/en-US/pending/edition-photo-card.webp +0 -0
- package/release-notes/i18n/en-US/pending/short-notification-buttons.json +1 -0
- package/release-notes/i18n/en-US/pending/version-heading-date-photo.json +5 -0
- package/scripts/release-notes.mjs +2 -1
- package/src/App.tsx +4 -1
- package/src/CmsPage.tsx +7 -2
- package/src/Licenses.tsx +4 -0
- package/src/Notifications.tsx +1 -1
- package/src/ReleaseNoteLines.tsx +17 -0
- package/src/ReleaseNoteSection.tsx +12 -0
- package/src/ReleaseNotes.tsx +49 -27
- package/src/Screen.tsx +2 -2
- package/src/UpdatesNotice.tsx +104 -69
- package/src/VersionLinePage.tsx +42 -0
- package/src/bundledNotes.ts +40 -5
- package/src/editor.css +4 -1
- package/src/i18n/da-DK/cms.ts +4 -0
- package/src/i18n/da-DK/library.ts +7 -4
- package/src/i18n/en-US/cms.ts +7 -0
- package/src/i18n/en-US/library.ts +12 -5
|
@@ -19,6 +19,11 @@ import {
|
|
|
19
19
|
imageKey,
|
|
20
20
|
parseImagePath,
|
|
21
21
|
withImageUrls,
|
|
22
|
+
editionOf,
|
|
23
|
+
testVersionDate,
|
|
24
|
+
changelogSections,
|
|
25
|
+
minorOf,
|
|
26
|
+
versionLines,
|
|
22
27
|
} from './releaseNotes.mjs';
|
|
23
28
|
|
|
24
29
|
const card = (id, overrides = {}) => ({ id, kind: 'card', title: `Title ${id}`, text: `Text ${id}`, ...overrides });
|
|
@@ -210,11 +215,11 @@ test('bundledNotes gives the whole minor line, newest first', () => {
|
|
|
210
215
|
['0.14.10', '0.14.1', '0.14.0'],
|
|
211
216
|
);
|
|
212
217
|
});
|
|
213
|
-
test('bundledNotes
|
|
218
|
+
test('bundledNotes keeps the older minors and leaves out newer ones', () => {
|
|
214
219
|
const files = { ...en('0.13.0', [line('a')]), ...en('0.13.5', [line('b')]), ...en('0.15.0', [line('c')]), ...en('0.14.0', [line('d')]) };
|
|
215
220
|
assert.deepEqual(
|
|
216
221
|
bundledNotes(files, {}, '0.14.0').map((e) => e.version),
|
|
217
|
-
['0.14.0'],
|
|
222
|
+
['0.14.0', '0.13.5', '0.13.0'],
|
|
218
223
|
);
|
|
219
224
|
});
|
|
220
225
|
test('bundledNotes ignores a newer version', () => {
|
|
@@ -230,13 +235,15 @@ test('bundledNotes takes a test version (npm tag next) without throwing: the lin
|
|
|
230
235
|
bundledNotes(files, {}, '0.14.2-next.0').map((e) => e.version),
|
|
231
236
|
['0.14.1', '0.14.0'],
|
|
232
237
|
);
|
|
233
|
-
assert.deepEqual(
|
|
238
|
+
assert.deepEqual(
|
|
239
|
+
bundledNotes(files, {}, '0.15.0-next.3').map((e) => e.version),
|
|
240
|
+
['0.14.2', '0.14.1', '0.14.0'],
|
|
241
|
+
);
|
|
234
242
|
});
|
|
235
243
|
test('bundledNotes gives nothing for something that is not a version', () => {
|
|
236
244
|
assert.deepEqual(bundledNotes(en('0.14.0', [line('a')]), {}, 'latest'), []);
|
|
237
245
|
});
|
|
238
|
-
test('bundledNotes gives an empty list without
|
|
239
|
-
assert.deepEqual(bundledNotes(en('0.13.0', [line('a')]), {}, '0.14.0'), []);
|
|
246
|
+
test('bundledNotes gives an empty list without notes or a changelog', () => {
|
|
240
247
|
assert.deepEqual(bundledNotes({}, {}, '0.14.0'), []);
|
|
241
248
|
});
|
|
242
249
|
test('bundledNotes sets the screenshot address of each version on its cards', () => {
|
|
@@ -360,3 +367,178 @@ test('withImageUrls sets the address on cards only and leaves the input alone',
|
|
|
360
367
|
});
|
|
361
368
|
|
|
362
369
|
test('withImageUrls gives undefined without notes', () => assert.equal(withImageUrls('0.14.0', undefined), undefined));
|
|
370
|
+
|
|
371
|
+
test("editionOf gives the edition of the version's minor line, with its photo", () => {
|
|
372
|
+
const files = {
|
|
373
|
+
'../release-notes/editions/0.13.json': { name: 'Lofoten' },
|
|
374
|
+
'../release-notes/editions/0.14.json': {
|
|
375
|
+
name: ' Braies ',
|
|
376
|
+
place: { 'en-US': 'Lago di Braies, Italy' },
|
|
377
|
+
photo: { by: 'A Photographer' },
|
|
378
|
+
},
|
|
379
|
+
};
|
|
380
|
+
const images = {
|
|
381
|
+
'../release-notes/editions/0.13.webp': '/a/lofoten.webp',
|
|
382
|
+
'../release-notes/editions/0.14.webp': '/a/braies.webp',
|
|
383
|
+
};
|
|
384
|
+
assert.deepEqual(editionOf(files, images, '0.14.2'), {
|
|
385
|
+
line: '0.14',
|
|
386
|
+
name: 'Braies',
|
|
387
|
+
place: { 'en-US': 'Lago di Braies, Italy' },
|
|
388
|
+
by: 'A Photographer',
|
|
389
|
+
image: '/a/braies.webp',
|
|
390
|
+
});
|
|
391
|
+
assert.equal(editionOf(files, images, '0.14.0').name, 'Braies');
|
|
392
|
+
assert.equal(editionOf(files, images, '0.14.3-next-20261107145215').name, 'Braies');
|
|
393
|
+
assert.equal(editionOf(files, images, '0.13.4').name, 'Lofoten');
|
|
394
|
+
assert.deepEqual(editionOf(files, images, '0.13.4').place, {});
|
|
395
|
+
assert.equal(editionOf(files, images, '0.13.4').by, null);
|
|
396
|
+
assert.equal(editionOf(files, images, '0.15.0'), undefined);
|
|
397
|
+
assert.equal(editionOf(files, images, '0.12.9'), undefined);
|
|
398
|
+
assert.equal(editionOf(files, images, 'not a version'), undefined);
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
test('editionOf skips an edition without a name or a photo', () => {
|
|
402
|
+
const files = { '../release-notes/editions/0.14.json': { name: 'Braies' }, '../release-notes/editions/0.15.json': { name: '' } };
|
|
403
|
+
assert.equal(editionOf(files, {}, '0.14.2'), undefined);
|
|
404
|
+
assert.equal(editionOf(files, { '../release-notes/editions/0.15.webp': '/x.webp' }, '0.15.0'), undefined);
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
test('released dates the version when given a day', () => {
|
|
408
|
+
const pending = { 'en-US': { a: { note: line('a'), imageBytes: null, imageSize: null } } };
|
|
409
|
+
assert.equal(released(pending, '0.14.3', '2026-11-08')['en-US'].file.date, '2026-11-08');
|
|
410
|
+
assert.equal('date' in released(pending, '0.14.3')['en-US'].file, false);
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
test('testVersionDate reads the day from a snapshot id', () => {
|
|
414
|
+
assert.equal(testVersionDate('0.14.3-next-20261107145215'), '2026-11-07');
|
|
415
|
+
assert.equal(testVersionDate('0.14.3'), undefined);
|
|
416
|
+
assert.equal(testVersionDate('0.14.3-next.0'), undefined);
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
test("bundledNotes gives each released version its file's date", () => {
|
|
420
|
+
const files = { '../release-notes/i18n/en-US/0.14.0.json': { version: '0.14.0', date: '2026-11-07', notes: [line('a')] } };
|
|
421
|
+
assert.equal(bundledNotes(files, {}, '0.14.0')[0].date, '2026-11-07');
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
test("bundledNotes puts a test version's merged notes first, under its version and the day it was made", () => {
|
|
425
|
+
const files = { '../release-notes/i18n/en-US/0.14.2.json': { version: '0.14.2', notes: [line('a')] } };
|
|
426
|
+
const pending = {
|
|
427
|
+
'../release-notes/i18n/en-US/pending/z.json': line('z'),
|
|
428
|
+
'../release-notes/i18n/en-US/pending/c.json': card('c'),
|
|
429
|
+
'../release-notes/i18n/da-DK/pending/c.json': card('c', { title: 'Kort' }),
|
|
430
|
+
};
|
|
431
|
+
const images = { '../release-notes/i18n/en-US/pending/c.webp': '/c.webp' };
|
|
432
|
+
const [first, second] = bundledNotes(files, images, '0.14.3-next-20261107145215', pending);
|
|
433
|
+
assert.equal(first.version, '0.14.3-next-20261107145215');
|
|
434
|
+
assert.equal(first.date, '2026-11-07');
|
|
435
|
+
assert.deepEqual(
|
|
436
|
+
first.notes['en-US'].map((n) => n.id),
|
|
437
|
+
['c', 'z'],
|
|
438
|
+
);
|
|
439
|
+
assert.equal(first.notes['en-US'][0].image, '/c.webp');
|
|
440
|
+
assert.equal(first.notes['da-DK'][0].title, 'Kort');
|
|
441
|
+
assert.equal(second.version, '0.14.2');
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
test('bundledNotes leaves out pending notes on a released version', () => {
|
|
445
|
+
const pending = { '../release-notes/i18n/en-US/pending/z.json': line('z') };
|
|
446
|
+
assert.deepEqual(bundledNotes({}, {}, '0.14.3', pending), []);
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
test("notesSince counts a test version's merged notes as new", () => {
|
|
450
|
+
const entries = [
|
|
451
|
+
{ version: '0.14.3-next-20261107145215', notes: { 'en-US': [line('z')] } },
|
|
452
|
+
{ version: '0.14.2', notes: { 'en-US': [line('a')] } },
|
|
453
|
+
];
|
|
454
|
+
assert.deepEqual(
|
|
455
|
+
notesSince(entries, '0.14.2', 'en-US').map((n) => n.id),
|
|
456
|
+
['z'],
|
|
457
|
+
);
|
|
458
|
+
assert.deepEqual(
|
|
459
|
+
notesSince(entries, '0.14.1', 'en-US').map((n) => n.id),
|
|
460
|
+
['z', 'a'],
|
|
461
|
+
);
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
const CHANGELOG = `# @morphemecms/cms
|
|
465
|
+
|
|
466
|
+
## 0.14.0
|
|
467
|
+
|
|
468
|
+
### Minor Changes
|
|
469
|
+
|
|
470
|
+
- a70c310: Apps can be turned off.
|
|
471
|
+
|
|
472
|
+
## 0.13.0
|
|
473
|
+
|
|
474
|
+
### Minor Changes
|
|
475
|
+
|
|
476
|
+
- 1193da4: The standard parts are in English.
|
|
477
|
+
|
|
478
|
+
### Patch Changes
|
|
479
|
+
|
|
480
|
+
- ccefd29: The licence checks know \`@app/self\`: an app that imports it no longer needs it in \`thirdParty\`, and
|
|
481
|
+
the site's licence list counts it as the site's own.
|
|
482
|
+
- 34f69c5: Open website opens in a new window.
|
|
483
|
+
|
|
484
|
+
## 0.12.0
|
|
485
|
+
|
|
486
|
+
## 0.11.0
|
|
487
|
+
|
|
488
|
+
- Plain line without a commit.
|
|
489
|
+
`;
|
|
490
|
+
|
|
491
|
+
test('changelogSections gives each version its changes as lines, newest first', () => {
|
|
492
|
+
const sections = changelogSections(CHANGELOG);
|
|
493
|
+
assert.deepEqual(
|
|
494
|
+
sections.map((s) => s.version),
|
|
495
|
+
['0.14.0', '0.13.0', '0.12.0', '0.11.0'],
|
|
496
|
+
);
|
|
497
|
+
assert.deepEqual(
|
|
498
|
+
sections[1].lines.map((l) => l.text),
|
|
499
|
+
[
|
|
500
|
+
'The standard parts are in English.',
|
|
501
|
+
"The licence checks know @app/self: an app that imports it no longer needs it in thirdParty, and the site's licence list counts it as the site's own.",
|
|
502
|
+
'Open website opens in a new window.',
|
|
503
|
+
],
|
|
504
|
+
);
|
|
505
|
+
assert.equal(sections[1].lines[0].id, '0.13.0-1193da4');
|
|
506
|
+
assert.equal(sections[1].lines[0].kind, 'line');
|
|
507
|
+
assert.deepEqual(sections[2].lines, []);
|
|
508
|
+
assert.equal(sections[3].lines[0].text, 'Plain line without a commit.');
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
test('bundledNotes adds the changelog versions that have no notes file, in English', () => {
|
|
512
|
+
const files = en('0.14.0', [line('a')]);
|
|
513
|
+
const entries = bundledNotes(files, {}, '0.14.0', {}, CHANGELOG);
|
|
514
|
+
assert.deepEqual(
|
|
515
|
+
entries.map((e) => e.version),
|
|
516
|
+
['0.14.0', '0.13.0', '0.11.0'],
|
|
517
|
+
);
|
|
518
|
+
assert.deepEqual(entries[0].notes, { 'en-US': [line('a')] });
|
|
519
|
+
assert.equal(entries[1].notes['en-US'].length, 3);
|
|
520
|
+
assert.equal(entries[1].notes['da-DK'], undefined);
|
|
521
|
+
});
|
|
522
|
+
|
|
523
|
+
test('minorOf gives the minor line', () => {
|
|
524
|
+
assert.equal(minorOf('0.14.3-next-20261107145215'), '0.14');
|
|
525
|
+
assert.equal(minorOf('0.9.1'), '0.9');
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
test('versionLines groups the entries by minor line, newest line first', () => {
|
|
529
|
+
const lines = versionLines([
|
|
530
|
+
{ version: '0.14.3-next-1' },
|
|
531
|
+
{ version: '0.14.2' },
|
|
532
|
+
{ version: '0.10.0' },
|
|
533
|
+
{ version: '0.9.1' },
|
|
534
|
+
{ version: '0.9.0' },
|
|
535
|
+
]);
|
|
536
|
+
assert.deepEqual(
|
|
537
|
+
lines.map((l) => [l.line, l.entries.map((e) => e.version)]),
|
|
538
|
+
[
|
|
539
|
+
['0.14', ['0.14.3-next-1', '0.14.2']],
|
|
540
|
+
['0.10', ['0.10.0']],
|
|
541
|
+
['0.9', ['0.9.1', '0.9.0']],
|
|
542
|
+
],
|
|
543
|
+
);
|
|
544
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@morphemecms/cms",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.3-next-20261107160925",
|
|
4
4
|
"description": "Morpheme CMS: the editor for a site built with Astro, its screens, its blocks and the rules a site gives it. See README.md.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Lars Adolfsen",
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Braies",
|
|
3
|
+
"place": {
|
|
4
|
+
"en-US": "Lago di Braies, South Tyrol, Italy",
|
|
5
|
+
"da-DK": "Lago di Braies, Sydtyrol, Italien"
|
|
6
|
+
},
|
|
7
|
+
"photo": {
|
|
8
|
+
"by": "Pietro De Grandi",
|
|
9
|
+
"source": "https://images.unsplash.com/photo-1501785888041-af3ef285b470",
|
|
10
|
+
"license": "https://unsplash.com/license"
|
|
11
|
+
}
|
|
12
|
+
}
|
|
Binary file
|
|
@@ -1,49 +1,50 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "0.14.0",
|
|
3
|
+
"date": "2026-11-07",
|
|
3
4
|
"notes": [
|
|
4
5
|
{
|
|
5
6
|
"id": "apps-turn-off",
|
|
6
7
|
"kind": "card",
|
|
7
|
-
"title": "
|
|
8
|
-
"text": "
|
|
8
|
+
"title": "Sæt en app på pause uden at miste indstillingerne",
|
|
9
|
+
"text": "Nu kan du slå en app fra og beholde dens indstillinger. Åbn appen under Apps, og slå Aktiveret fra. Slå den til igen, når du vil."
|
|
9
10
|
},
|
|
10
11
|
{
|
|
11
12
|
"id": "developer-menu",
|
|
12
13
|
"kind": "line",
|
|
13
|
-
"text": "Avanceret hedder nu Udvikler
|
|
14
|
+
"text": "Avanceret under Indstillinger hedder nu Udvikler, og dine gamle links virker stadig"
|
|
14
15
|
},
|
|
15
16
|
{
|
|
16
17
|
"id": "dynamic-lists-page",
|
|
17
18
|
"kind": "line",
|
|
18
|
-
"text": "Lister hedder nu Dynamiske lister
|
|
19
|
+
"text": "Lister i menuen hedder nu Dynamiske lister og åbner en side med alle dine lister"
|
|
19
20
|
},
|
|
20
21
|
{
|
|
21
22
|
"id": "editor-footer",
|
|
22
23
|
"kind": "card",
|
|
23
|
-
"title": "
|
|
24
|
-
"text": "
|
|
24
|
+
"title": "Tjek GitHub og Cloudflare",
|
|
25
|
+
"text": "Hvis du ikke kan gemme eller udgive, så se, om GitHub og Cloudflare virker. Rul ned til bunden af editoren, og tryk på Driftsstatus. Den tjekker kun de tjenester, din hjemmeside bruger."
|
|
25
26
|
},
|
|
26
27
|
{
|
|
27
28
|
"id": "editor-toolbar-dock",
|
|
28
29
|
"kind": "line",
|
|
29
|
-
"text": "På en telefon
|
|
30
|
+
"text": "På en telefon fylder værktøjslinjen til tekst mindre"
|
|
30
31
|
},
|
|
31
32
|
{
|
|
32
33
|
"id": "google-preview-closer",
|
|
33
34
|
"kind": "card",
|
|
34
|
-
"title": "
|
|
35
|
-
"text": "
|
|
35
|
+
"title": "Se din side, som Google viser den",
|
|
36
|
+
"text": "Forhåndsvisningen af Google-resultatet ligner nu Googles eget på både telefon og computer, og dit vigtigste søgeord står med fed. Åbn en side eller et blogindlæg, og se under Søgemaskiner."
|
|
36
37
|
},
|
|
37
38
|
{
|
|
38
39
|
"id": "morpheme-connection-page",
|
|
39
40
|
"kind": "line",
|
|
40
|
-
"text": "
|
|
41
|
+
"text": "Forbindelse til Appstore ligger nu på siden Morpheme under Indstillinger"
|
|
41
42
|
},
|
|
42
43
|
{
|
|
43
44
|
"id": "quiet-lamps-wander",
|
|
44
45
|
"kind": "card",
|
|
45
46
|
"title": "Se, hvad der er nyt",
|
|
46
|
-
"text": "
|
|
47
|
+
"text": "Efter hver opdatering får du nu et kort overblik over, hvad der er nyt. Alle noterne finder du på siden Morpheme under Indstillinger."
|
|
47
48
|
}
|
|
48
49
|
]
|
|
49
50
|
}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "0.14.1",
|
|
3
|
+
"date": "2026-11-07",
|
|
3
4
|
"notes": [
|
|
4
5
|
{
|
|
5
6
|
"id": "drawer-back-changes-screen",
|
|
6
7
|
"kind": "line",
|
|
7
|
-
"text": "
|
|
8
|
+
"text": "Swiper du tilbage på en telefon, mens menuen er åben, lukker menuen, og du kommer til skærmen før"
|
|
8
9
|
},
|
|
9
10
|
{
|
|
10
11
|
"id": "notes-from-package",
|
|
11
12
|
"kind": "line",
|
|
12
|
-
"text": "
|
|
13
|
+
"text": "Noter som disse vises nu, lige når du har opdateret"
|
|
13
14
|
}
|
|
14
15
|
]
|
|
15
16
|
}
|
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "0.14.2",
|
|
3
|
+
"date": "2026-11-07",
|
|
3
4
|
"notes": [
|
|
4
5
|
{
|
|
5
6
|
"id": "footer-scrolls-above-fab",
|
|
6
7
|
"kind": "line",
|
|
7
|
-
"text": "På en telefon
|
|
8
|
+
"text": "På en telefon skjuler plusknappen ikke længere linkene nederst i editoren"
|
|
8
9
|
},
|
|
9
10
|
{
|
|
10
11
|
"id": "lists-follow-md3",
|
|
11
12
|
"kind": "line",
|
|
12
|
-
"text": "Lister i editoren
|
|
13
|
+
"text": "Lister i editoren har større tekst og skiller sig bedre ud fra siden"
|
|
13
14
|
},
|
|
14
15
|
{
|
|
15
16
|
"id": "update-card-whats-new",
|
|
16
17
|
"kind": "card",
|
|
17
|
-
"title": "Nyhederne
|
|
18
|
-
"text": "Efter en opdatering
|
|
18
|
+
"title": "Nyhederne står på din startskærm",
|
|
19
|
+
"text": "Efter en opdatering viser startskærmen øverst den nye version og de vigtigste nyheder. Tryk på Se, hvad der er nyt for at læse det hele."
|
|
19
20
|
}
|
|
20
21
|
]
|
|
21
22
|
}
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "id": "short-notification-buttons", "kind": "line", "text": "Knapperne under Notifikationer hedder nu Ryd og Indstillinger" }
|
|
@@ -1,49 +1,50 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "0.14.0",
|
|
3
|
+
"date": "2026-11-07",
|
|
3
4
|
"notes": [
|
|
4
5
|
{
|
|
5
6
|
"id": "apps-turn-off",
|
|
6
7
|
"kind": "card",
|
|
7
|
-
"title": "
|
|
8
|
-
"text": "
|
|
8
|
+
"title": "Pause an app without losing its settings",
|
|
9
|
+
"text": "You can now turn an app off and keep its settings. Open the app under Apps and turn off Enabled. Turn it on again whenever you like."
|
|
9
10
|
},
|
|
10
11
|
{
|
|
11
12
|
"id": "developer-menu",
|
|
12
13
|
"kind": "line",
|
|
13
|
-
"text": "Advanced
|
|
14
|
+
"text": "Advanced under Settings is now called Developer, and your old links still work"
|
|
14
15
|
},
|
|
15
16
|
{
|
|
16
17
|
"id": "dynamic-lists-page",
|
|
17
18
|
"kind": "line",
|
|
18
|
-
"text": "Lists is now Dynamic lists
|
|
19
|
+
"text": "Lists in the menu is now Dynamic lists and opens a page with all your lists"
|
|
19
20
|
},
|
|
20
21
|
{
|
|
21
22
|
"id": "editor-footer",
|
|
22
23
|
"kind": "card",
|
|
23
|
-
"title": "
|
|
24
|
-
"text": "
|
|
24
|
+
"title": "Check GitHub and Cloudflare",
|
|
25
|
+
"text": "If you can’t save or publish, see whether GitHub and Cloudflare are working. Scroll to the bottom of the editor and tap System status. It checks only the services your website uses."
|
|
25
26
|
},
|
|
26
27
|
{
|
|
27
28
|
"id": "editor-toolbar-dock",
|
|
28
29
|
"kind": "line",
|
|
29
|
-
"text": "On a phone, the text toolbar
|
|
30
|
+
"text": "On a phone, the text toolbar takes up less room"
|
|
30
31
|
},
|
|
31
32
|
{
|
|
32
33
|
"id": "google-preview-closer",
|
|
33
34
|
"kind": "card",
|
|
34
|
-
"title": "
|
|
35
|
-
"text": "
|
|
35
|
+
"title": "See your page as Google shows it",
|
|
36
|
+
"text": "The Google preview now looks like the real result on a phone and a computer, with your main keyword in bold. Open a page or blog post and look under Search engines."
|
|
36
37
|
},
|
|
37
38
|
{
|
|
38
39
|
"id": "morpheme-connection-page",
|
|
39
40
|
"kind": "line",
|
|
40
|
-
"text": "
|
|
41
|
+
"text": "Store connection is now on the Morpheme page under Settings"
|
|
41
42
|
},
|
|
42
43
|
{
|
|
43
44
|
"id": "quiet-lamps-wander",
|
|
44
45
|
"kind": "card",
|
|
45
|
-
"title": "See what
|
|
46
|
-
"text": "
|
|
46
|
+
"title": "See what’s new",
|
|
47
|
+
"text": "After each update, you now get a short summary of what’s new. You’ll find all the notes on the Morpheme page under Settings."
|
|
47
48
|
}
|
|
48
49
|
]
|
|
49
50
|
}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "0.14.1",
|
|
3
|
+
"date": "2026-11-07",
|
|
3
4
|
"notes": [
|
|
4
5
|
{
|
|
5
6
|
"id": "drawer-back-changes-screen",
|
|
6
7
|
"kind": "line",
|
|
7
|
-
"text": "On a phone, swiping back with the menu open
|
|
8
|
+
"text": "On a phone, swiping back with the menu open closes the menu and takes you to the previous screen"
|
|
8
9
|
},
|
|
9
10
|
{
|
|
10
11
|
"id": "notes-from-package",
|
|
11
12
|
"kind": "line",
|
|
12
|
-
"text": "
|
|
13
|
+
"text": "Notes like these now show right after you update"
|
|
13
14
|
}
|
|
14
15
|
]
|
|
15
16
|
}
|
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "0.14.2",
|
|
3
|
+
"date": "2026-11-07",
|
|
3
4
|
"notes": [
|
|
4
5
|
{
|
|
5
6
|
"id": "footer-scrolls-above-fab",
|
|
6
7
|
"kind": "line",
|
|
7
|
-
"text": "On a phone,
|
|
8
|
+
"text": "On a phone, the add button no longer hides the links at the bottom of the editor"
|
|
8
9
|
},
|
|
9
10
|
{
|
|
10
11
|
"id": "lists-follow-md3",
|
|
11
12
|
"kind": "line",
|
|
12
|
-
"text": "Lists in the editor
|
|
13
|
+
"text": "Lists in the editor have larger text and stand out more from the page"
|
|
13
14
|
},
|
|
14
15
|
{
|
|
15
16
|
"id": "update-card-whats-new",
|
|
16
17
|
"kind": "card",
|
|
17
|
-
"title": "What
|
|
18
|
-
"text": "After an update,
|
|
18
|
+
"title": "What’s new, right on your start screen",
|
|
19
|
+
"text": "After an update, the top of the start screen shows the new version and its main news. Tap See what’s new to read it all."
|
|
19
20
|
}
|
|
20
21
|
]
|
|
21
22
|
}
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "id": "short-notification-buttons", "kind": "line", "text": "The buttons under Notifications are now Clear and Settings" }
|
|
@@ -17,7 +17,8 @@ if (problems.length > 0) {
|
|
|
17
17
|
process.exit(1);
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
// The day it is released, for the Morpheme page ("New in …" with its date).
|
|
21
|
+
const result = released(pending, version, new Date().toISOString().slice(0, 10));
|
|
21
22
|
const targets = Object.keys(result).map((locale) => join(root, 'release-notes', 'i18n', locale, `${version}.json`));
|
|
22
23
|
const existing = targets.filter((target) => existsSync(target));
|
|
23
24
|
if (existing.length > 0) {
|
package/src/App.tsx
CHANGED
|
@@ -33,7 +33,8 @@
|
|
|
33
33
|
// ("Promovering"), its own and the apps' (BlockParts.tsx), and developer/parts/values the
|
|
34
34
|
// theme's design tokens, "Værdier" (Tokens.tsx)
|
|
35
35
|
// block-settings the blocks that can be put in, "Blokindstillinger" (BlockSettings.tsx)
|
|
36
|
-
// morpheme "Morpheme", under "Indstillinger": the CMS's version, a newer one and its notes, an update's progress (CmsPage.tsx)
|
|
36
|
+
// morpheme "Morpheme", under "Indstillinger": the CMS's version, a newer one and its notes, an update's progress (CmsPage.tsx),
|
|
37
|
+
// and morpheme/<line> an older minor line's notes, e.g. morpheme/0.13 (VersionLinePage.tsx)
|
|
37
38
|
// licenses "Licenser", under "Indstillinger": the licences of what the site and the editor are made with, and
|
|
38
39
|
// licenses/<id> one with its text (Licenses.tsx)
|
|
39
40
|
// status "System status", from the footer: GitHub's and Cloudflare's status (ServiceStatus.tsx)
|
|
@@ -100,6 +101,7 @@ import BrandForm from './BrandForm';
|
|
|
100
101
|
import BlockSettings from './BlockSettings';
|
|
101
102
|
import Advanced, { CACHING_ROUTE } from './Advanced';
|
|
102
103
|
import CmsPage, { CMS_ROUTE } from './CmsPage';
|
|
104
|
+
import { VersionLinePage } from './VersionLinePage';
|
|
103
105
|
import Licenses, { LICENSES_ROUTE, LicensePage } from './Licenses';
|
|
104
106
|
import ServiceStatus, { STATUS_ROUTE } from './ServiceStatus';
|
|
105
107
|
import { StoreThemePage } from './ThemeStore';
|
|
@@ -791,6 +793,7 @@ function Page({ route, files, env, user, builtAt, onLogout }: PageProps) {
|
|
|
791
793
|
if (route === DEV_MENU_ROUTE) return <Developer />;
|
|
792
794
|
if (route === CACHING_ROUTE) return <Advanced env={env} />;
|
|
793
795
|
if (route === CMS_ROUTE) return <CmsPage />;
|
|
796
|
+
if (route.startsWith(`${CMS_ROUTE}/`)) return <VersionLinePage key={route} line={route.slice(CMS_ROUTE.length + 1)} />;
|
|
794
797
|
if (route === LICENSES_ROUTE) return <Licenses />;
|
|
795
798
|
if (route === STATUS_ROUTE) return <ServiceStatus />;
|
|
796
799
|
if (route.startsWith(`${LICENSES_ROUTE}/`)) return <LicensePage key={route} id={route.slice(LICENSES_ROUTE.length + 1)} />;
|
package/src/CmsPage.tsx
CHANGED
|
@@ -10,7 +10,9 @@ import { ReleaseNotes, type VersionNotes } from './ReleaseNotes';
|
|
|
10
10
|
import { Button, EmptyNote, Group, ListItem, ProblemNote } from './ui';
|
|
11
11
|
import { backFrom } from './site';
|
|
12
12
|
import { cmsView } from './cmsView.mjs';
|
|
13
|
-
import { runningNotes } from './bundledNotes';
|
|
13
|
+
import { runningLine, runningNotes } from './bundledNotes';
|
|
14
|
+
import { EarlierVersions } from './VersionLinePage';
|
|
15
|
+
import { minorOf } from '../lib/releaseNotes.mjs';
|
|
14
16
|
import { snackbar } from '../lib/snackbar';
|
|
15
17
|
import { t } from './i18n';
|
|
16
18
|
import { when } from './when';
|
|
@@ -101,13 +103,15 @@ export default function CmsPage() {
|
|
|
101
103
|
}
|
|
102
104
|
|
|
103
105
|
const reason = view && reasonOf(view);
|
|
106
|
+
// The running minor line's versions; the older lines are on pages of their own (EarlierVersions).
|
|
107
|
+
const yourLine = runningNotes.filter((entry) => minorOf(entry.version) === runningLine);
|
|
104
108
|
return (
|
|
105
109
|
<Screen title={t.common.parts.morpheme} back={backFrom(CMS_ROUTE)}>
|
|
106
110
|
{problem && <ProblemNote alert>{problem}</ProblemNote>}
|
|
107
111
|
{!view && !problem && <EmptyNote busy>{t.app.loading}</EmptyNote>}
|
|
108
112
|
{view && (
|
|
109
113
|
<>
|
|
110
|
-
{
|
|
114
|
+
{yourLine.length > 0 && <ReleaseNotes title={t.cms.newInYourVersion} entries={yourLine} />}
|
|
111
115
|
<Group>
|
|
112
116
|
<ListItem icon={Info} headline={t.cms.running(view.running)} supporting={view.latest ? undefined : t.cms.upToDate} />
|
|
113
117
|
<ListItem icon={Clock} headline={view.checkedAt ? t.cms.checked(when(new Date(view.checkedAt))) : t.cms.notChecked} />
|
|
@@ -126,6 +130,7 @@ export default function CmsPage() {
|
|
|
126
130
|
{view.notes.length > 0 && <ReleaseNotes title={t.cms.whatsNew} entries={view.notes} />}
|
|
127
131
|
</>
|
|
128
132
|
)}
|
|
133
|
+
{view && <EarlierVersions />}
|
|
129
134
|
<MorphemeConnection />
|
|
130
135
|
</Screen>
|
|
131
136
|
);
|
package/src/Licenses.tsx
CHANGED
|
@@ -17,6 +17,7 @@ import { apps } from './registry';
|
|
|
17
17
|
import { themes } from './themes';
|
|
18
18
|
import { byText } from './schema';
|
|
19
19
|
import { PACKAGE } from '../lib/cms-version.mjs';
|
|
20
|
+
import { editionPhotos } from './bundledNotes';
|
|
20
21
|
import { locale, t } from './i18n';
|
|
21
22
|
import {
|
|
22
23
|
CMS_NAME,
|
|
@@ -242,6 +243,8 @@ export function LicensePage({ id }: { id: string }) {
|
|
|
242
243
|
const isCms = work?.id === PACKAGE;
|
|
243
244
|
const name = isCms ? t.licenses.own(CMS_NAME) : (work?.name ?? (owner ? t.licenses.own(ownerName(owner)) : t.common.parts.licenses));
|
|
244
245
|
const text = work?.text ?? owner?.text;
|
|
246
|
+
// An edition's photo (editions/<line>, editionWorks in lib/licenses.mjs): the whole photo, uncropped.
|
|
247
|
+
const photo = work?.id.startsWith('editions/') ? editionPhotos[work.id.slice('editions/'.length)] : undefined;
|
|
245
248
|
const back = { href: `#${LICENSES_ROUTE}`, label: t.common.parts.licenses };
|
|
246
249
|
return (
|
|
247
250
|
<Screen title={name} wide back={back}>
|
|
@@ -258,6 +261,7 @@ export function LicensePage({ id }: { id: string }) {
|
|
|
258
261
|
<OwnRow owner={(work ?? owner)!} name={isCms ? CMS_NAME : ownerName(owner!)} open={false} />
|
|
259
262
|
)}
|
|
260
263
|
</Group>
|
|
264
|
+
{photo && <img src={photo} alt={work!.name} className="mb-8 block h-auto w-full rounded-xl" />}
|
|
261
265
|
<section className="mb-8">
|
|
262
266
|
<GroupTitle>{t.licenses.text}</GroupTitle>
|
|
263
267
|
{work?.standard && <SupportingText className="mb-3 px-4">{t.licenses.standardText(work.license)}</SupportingText>}
|
package/src/Notifications.tsx
CHANGED
|
@@ -93,7 +93,7 @@ export default function Notifications() {
|
|
|
93
93
|
// The phone's back gesture closes the sheet only (useSheetBack).
|
|
94
94
|
useSheetBack(open, closeNotifications, 'notifications');
|
|
95
95
|
|
|
96
|
-
// Another address (a notification's link, "
|
|
96
|
+
// Another address (a notification's link, "Settings") closes it.
|
|
97
97
|
useEffect(() => {
|
|
98
98
|
if (!open) return;
|
|
99
99
|
window.addEventListener('hashchange', closeNotifications);
|