Name an item without a title from its own text, not "(untitled)" (#116)

RSS 2.0 makes an item's title optional, and some blogs leave it out on purpose: Scripting News
titles almost none of its posts. Fifty rows of "(untitled)" said nothing about any of them.

entryName gives an item its title, or the opening of its text (HTML read through DOMParser, an
inert document that loads nothing; cut at a word near 120 characters), or its file's name, or
its show and date, with a flag for a name that is not a title. The list sets that one in the
regular weight, as the text it is rather than a heading; the reader leaves out the heading so
the post starts with itself; the player, the lock screen, Currently Listening, the native shell,
Share and the queued toast use the same name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-02 20:46:47 +00:00
parent 0395717c14
commit d238681ec1
7 changed files with 47 additions and 8 deletions

View File

@@ -972,6 +972,21 @@ test('artwork comes from iPX, kept, and only as an image', async ({ page }) => {
expect((await page.request.get('/api/art?u=' + encodeURIComponent('http://127.0.0.1:8792/show.xml'))).status()).toBe(404);
});
test('an item without a title is named from its text, then its file, then its show and date', async ({ page }) => {
const names = await page.evaluate(() => [
entryName({ title: 'A Title' }),
entryName({ title: ' ', description: '<p>I like the way <b>AI</b> is evolving.</p><img src="x.png">' }),
entryName({ description: '<p>' + 'word '.repeat(40) + '</p>' }).text.length,
entryName({ enclosures: [{ url: 'https://k.example/media/KARTAS691.mp3?x=1' }] }),
entryName({ feed_id: 'nobody', published: 0 }),
]);
expect(names[0]).toEqual({ text: 'A Title', derived: false });
expect(names[1]).toEqual({ text: 'I like the way AI is evolving.', derived: true });
expect(names[2]).toBeLessThanOrEqual(121); // cut at a word, with …
expect(names[3]).toEqual({ text: 'KARTAS691', derived: true });
expect(names[4]).toEqual({ text: 'nobody', derived: true });
});
test('a deleted file looks as if it was never downloaded', async ({ page }) => {
// Other people subscribe to Picture Blog by now, so both prompts come; take them.
page.on('dialog', d => d.accept());