feat(notes): første linje er titlen, resten er brødtekst
Release / Build and publish image (push) Failing after 9m57s
Release / Build and publish image (push) Failing after 9m57s
En ny note åbner på sin titel, og linjen efter er brødtekst — uden at man vælger noget. Det er det, Apple Notes gør, og det er også hvad listen har brug for: første linje bliver notens navn, så en note, der begynder i brødtekst, hedder sin egen første sætning. To ting undervejs. Reserven for en tom note blev aldrig brugt, fordi en tom tekst ikke gengives som ingenting men som ét tomt afsnit — den prøves nu på teksten og ikke på resultatet. Og Chromium svarer på retur med et bart <div>, som læses som brødtekst men ikke er formateret som det: afstanden mellem afsnit forsvandt stille i det øjeblik, man trykkede retur frem for at vælge Brødtekst i menuen. Listen viste desuden den rå Markdown i forhåndsvisningen — "# Møde med Anders" og "**fed**" — hvilket er præcis det, editoren blev bygget for at holde op med at vise. Den viser nu sætningen frem for notationen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
f557d319ca
commit
3223989a9d
@@ -29,7 +29,13 @@
|
||||
let loadedId = $state(null);
|
||||
$effect(() => {
|
||||
if (!editor || !note || note.id === loadedId) return;
|
||||
editor.innerHTML = markdownToHtml(note.body) || '<p><br></p>';
|
||||
// An empty note opens on its title. That is what Apple Notes does, and it is
|
||||
// also what the list needs: the first line becomes the name of the note, so a
|
||||
// note whose first line is body text is a note called by its first sentence.
|
||||
//
|
||||
// Tested on the text and not on the rendered result: an empty body renders as
|
||||
// one empty paragraph, not as nothing, so a falsy check here never fired.
|
||||
editor.innerHTML = note.body.trim() ? markdownToHtml(note.body) : '<h1><br></h1>';
|
||||
loadedId = note.id;
|
||||
active = {};
|
||||
});
|
||||
@@ -92,7 +98,51 @@
|
||||
onchange?.(htmlToMarkdown(editor));
|
||||
}
|
||||
|
||||
/** The block the caret is standing in. */
|
||||
function currentBlock() {
|
||||
const selection = window.getSelection();
|
||||
if (!selection || !selection.anchorNode || !editor) return null;
|
||||
let node = selection.anchorNode;
|
||||
while (node && node.parentNode !== editor) node = node.parentNode;
|
||||
return node?.nodeType === Node.ELEMENT_NODE ? node : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Title for the first line, body for everything after it.
|
||||
*
|
||||
* Run after the browser has split the block on Enter, because until then there
|
||||
* is no second block to change. Pressing return at the end of a heading leaves
|
||||
* the caret in another heading in most browsers, and a note where every line is
|
||||
* a title is a note with no title at all.
|
||||
*/
|
||||
function keepTitleFirst() {
|
||||
const block = currentBlock();
|
||||
if (!block) return;
|
||||
|
||||
// A heading that is not the first line becomes body.
|
||||
if (block.tagName === 'H1' && block !== editor.firstElementChild) {
|
||||
document.execCommand('formatBlock', false, 'p');
|
||||
return;
|
||||
}
|
||||
|
||||
// And the browser's own container becomes a paragraph. Chromium answers Enter
|
||||
// with a bare <div>, which reads as body but is not styled as one — so the
|
||||
// spacing between paragraphs quietly disappears the moment somebody presses
|
||||
// return rather than choosing Brødtekst from the menu.
|
||||
if (block.tagName === 'DIV') {
|
||||
document.execCommand('formatBlock', false, 'p');
|
||||
}
|
||||
}
|
||||
|
||||
function onkeydown(event) {
|
||||
if (event.key === 'Enter' && !event.shiftKey) {
|
||||
// After the split, not before it.
|
||||
setTimeout(() => {
|
||||
keepTitleFirst();
|
||||
changed();
|
||||
}, 0);
|
||||
return;
|
||||
}
|
||||
// The shortcuts people already have in their fingers. execCommand handles
|
||||
// bold and italic itself; underline and strikethrough are claimed here so
|
||||
// they behave the same way.
|
||||
|
||||
Reference in New Issue
Block a user