core: $headline$ format should get 60 chars from first p or h tag (#9658)

* core: note title headline format should get content from first p or h tag
* also decrease character limit to 60

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* Apply suggestion from @thecodrr

Signed-off-by: Abdullah Atta <thecodrr@protonmail.com>

---------

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
Signed-off-by: Abdullah Atta <thecodrr@protonmail.com>
Co-authored-by: Abdullah Atta <abdullahatta@streetwriters.co>
This commit is contained in:
01zulfi
2026-04-06 09:20:21 +05:00
committed by GitHub
parent 02b96470bc
commit 413ca61ef5
4 changed files with 27 additions and 6 deletions

View File

@@ -40,7 +40,7 @@ Go to `Settings` > `Editor` > `Title format` to customize the title formatting.
You can use a combination of above templates in the note title. For example `Note $count$ - $date$` will become `Note 150 - 06-22-2023`.
**$headline$**: Up to first 10 words of the note's headline. This will keep updating the title as headline of the note changes until you manually edit the title. Shouldn't be used in combination with other templates.
**$headline$**: Up to first 60 characters of the note's first paragraph or heading. This will keep updating the title as headline of the note changes until you manually edit the title. Shouldn't be used in combination with other templates.
## Paragraph spacing

View File

@@ -186,14 +186,15 @@ test("note title with headline format should keep generating headline title unti
[
["simple p tag", "<p>headline</p>", "headline"],
["across multiple tags", "<h1>title<h1><ol><li>list</li></ol>", "titlelist"],
["across multiple tags", "<h1>title</h1><ol><li>list</li></ol>", "title"],
["empty first p tag", "<p></p><p>actual title</p>", "actual title"],
[
"content with exceeded HEADLINE_CHARACTER_LIMIT",
"<p><strong>head</strong><em>line</em></p><h1>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam rutrum ex ac eros egestas, ut rhoncus felis faucibus. Mauris tempor orci nisl, vitae pulvinar turpis convallis n</h1>",
"headlineLorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam rutrum ex ac eros egestas, ut rhoncus felis faucibus. Mauris tempor orci nisl,"
"<p><strong>head</strong><em>line</em>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam rutrum ex ac eros egestas, ut rhoncus felis faucibus. Mauris tempor orci nisl, vitae pulvinar turpis convallis n</p>",
"headlineLorem ipsum dolor sit amet, consectetur adipiscing e"
]
].forEach(([testCase, content, expectedHeadline]) => {
test(`note title with headline format should generate headline title up to 150 characters - ${testCase}`, () =>
test(`note title with headline format should generate headline title up to 60 characters - ${testCase}`, () =>
noteTest().then(async ({ db }) => {
await db.settings.setTitleFormat("$headline$");
const id = await db.notes.add({

View File

@@ -94,7 +94,7 @@ export class Tiptap {
}
toTitle() {
return extractTitle(this.data, 150);
return extractTitle(this.data, 60);
}
// isEmpty() {

View File

@@ -72,11 +72,31 @@ export function extractHeadline(html: string) {
return text;
}
const TITLE_SOURCE_TAGS = ["p", "h1", "h2", "h3", "h4", "h5", "h6"];
export function extractTitle(html: string, characterLimit: number) {
let text = "";
let rootTag: string | undefined = undefined;
const parser = new Parser(
{
onopentag: (name) => {
if (!rootTag && TITLE_SOURCE_TAGS.includes(name)) {
rootTag = name;
}
},
onclosetag: (name) => {
if (name === rootTag) {
if (text) {
parser.pause();
parser.end();
} else {
rootTag = undefined;
}
}
},
ontext: (data) => {
if (!rootTag) return;
text += data;
if (text.length > characterLimit) {
text = text.slice(0, characterLimit);