Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions examples/07-collaboration/14-suggestion-gallery/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ type Mode = "suggestions" | "versioning";
const FIXES: { value: VersionDiffFixes | undefined; label: string }[] = [
{ value: undefined, label: "Default" },
{ value: "implicitDeleteAttribution", label: "Implicit delete attribution" },
{
value: "implicitDeleteAttributionAndRecreatedBlocks",
label: "+ re-created blocks",
},
];
const ALL_FIXES: ExperimentalVersionDiffs = {
versionDiffFixes: FIXES[FIXES.length - 1].value,
Expand Down
64 changes: 64 additions & 0 deletions examples/07-collaboration/14-suggestion-gallery/src/scenarios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,26 @@ function posBeforeText(editor: GalleryEditor, text: string): number {
return pos;
}

// Versioning notes for a block copy: a type change or a move stores a copy of
// the block, which the `recreatedBlocks` fix shows once.
const typeChangeNote: Feedback = {
severity: "info",
when: { recreatedBlocks: true },
note: "Versioning shows the type change as a formatting change.",
};
const moveNote: Feedback = {
severity: "info",
when: { recreatedBlocks: true },
note: "Versioning shows the block as moved: at its new place, and struck through at its old place unless it was only indented or outdented.",
};
function lostEditNote(user: string): Feedback {
return {
severity: "info",
when: { recreatedBlocks: true },
note: `Versioning shows only the type change: the result doesn't have ${user}'s edit, so the diff doesn't show it.`,
};
}

export const scenarios: SuggestionScenario[] = [
{
kind: "single",
Expand Down Expand Up @@ -241,12 +261,14 @@ export const scenarios: SuggestionScenario[] = [
kind: "single",
id: "nest-bullet-existing",
feedback: [
moveNote,
{
severity: "low",
note: "Nested bullets all render as • instead of •/◦/▪ — the suggestion-mark wrappers (display: contents) break the depth-detecting CSS chains. Fix: compute each bullet's nesting level in JS and expose it as data-bullet-level, then pick the glyph with a wrapper-independent attribute selector (as numbered lists do with data-index).",
},
{
severity: "high",
when: { recreatedBlocks: false },
note: "Indenting re-creates Parent and Child as new blocks (the schema fix stores a block that gains or loses its children as a new block). The diff therefore shows both as deleted and inserted again, all credited to whoever indented.",
},
],
Expand Down Expand Up @@ -413,8 +435,10 @@ export const scenarios: SuggestionScenario[] = [
kind: "single",
id: "type-list-to-paragraph",
feedback: [
typeChangeNote,
{
severity: "high",
when: { recreatedBlocks: false },
note: "Changing the type re-creates the block as a new one (with the schema fix, a block's type can't change in place). The diff therefore shows it as deleted and inserted again, all credited to whoever changed the type.",
},
],
Expand All @@ -435,8 +459,10 @@ export const scenarios: SuggestionScenario[] = [
kind: "single",
id: "type-paragraph-to-heading",
feedback: [
typeChangeNote,
{
severity: "high",
when: { recreatedBlocks: false },
note: "Changing the type re-creates the block as a new one (with the schema fix, a block's type can't change in place). The diff therefore shows it as deleted and inserted again, all credited to whoever changed the type.",
},
],
Expand Down Expand Up @@ -599,8 +625,10 @@ export const scenarios: SuggestionScenario[] = [
kind: "single",
id: "move-paragraph-up",
feedback: [
moveNote,
{
severity: "high",
when: { recreatedBlocks: false },
note: "Moving re-creates the block as a new one at its new place. The diff therefore shows it as deleted at its old place and inserted at its new one, all credited to the mover.",
},
],
Expand All @@ -620,8 +648,10 @@ export const scenarios: SuggestionScenario[] = [
kind: "single",
id: "move-paragraph-with-children",
feedback: [
moveNote,
{
severity: "high",
when: { recreatedBlocks: false },
note: "Moving re-creates the block, with its child, as a new one at its new place. The diff therefore shows it as deleted at its old place and inserted at its new one, all credited to the mover.",
},
],
Expand All @@ -646,8 +676,10 @@ export const scenarios: SuggestionScenario[] = [
kind: "single",
id: "nesting-indent",
feedback: [
moveNote,
{
severity: "high",
when: { recreatedBlocks: false },
note: "Indenting re-creates N0 and N1 as new blocks (the schema fix stores a block that gains or loses its children as a new block). The diff therefore shows both as deleted and inserted again, all credited to whoever indented.",
},
],
Expand All @@ -669,8 +701,10 @@ export const scenarios: SuggestionScenario[] = [
kind: "single",
id: "nesting-unindent",
feedback: [
moveNote,
{
severity: "high",
when: { recreatedBlocks: false },
note: "Outdenting re-creates N0 and N1 as new blocks (the schema fix stores a block that gains or loses its children as a new block). The diff therefore shows N0 and N1 as deleted and inserted again, all credited to whoever outdented.",
},
],
Expand All @@ -694,8 +728,10 @@ export const scenarios: SuggestionScenario[] = [
kind: "single",
id: "nesting-change-parent-type",
feedback: [
typeChangeNote,
{
severity: "high",
when: { recreatedBlocks: false },
note: "Changing the type re-creates N0, children included, as a new block (with the schema fix, a block's type can't change in place). The diff therefore shows it as deleted and inserted again, all credited to whoever changed the type.",
},
],
Expand Down Expand Up @@ -1047,6 +1083,12 @@ export const scenarios: SuggestionScenario[] = [
feedback: [
{
severity: "high",
when: { recreatedBlocks: true },
note: "Versioning shows N0 unchanged and N2 as moved, but N1's two copies as inserted by A and by B.",
},
{
severity: "high",
when: { recreatedBlocks: false },
note: "The diff also shows N0 and N2 as deleted and inserted again: indenting re-creates blocks (see Indent a block).",
},
{
Expand Down Expand Up @@ -1075,12 +1117,18 @@ export const scenarios: SuggestionScenario[] = [
kind: "concurrent",
id: "concurrent-indent-vs-edit",
feedback: [
{
severity: "info",
when: { recreatedBlocks: true },
note: "Versioning shows N0 unchanged and N1 as moved. The result doesn't have B's edit, so the diff doesn't show it.",
},
{
severity: "low",
note: "B's edit is lost: A's indent re-creates N1 as a new block, which doesn't have B's concurrent edit.",
},
{
severity: "high",
when: { recreatedBlocks: false },
note: "The diff also shows N0 and N1 as deleted and inserted again, all credited to A: indenting re-creates blocks (see Indent a block).",
},
],
Expand All @@ -1106,6 +1154,12 @@ export const scenarios: SuggestionScenario[] = [
feedback: [
{
severity: "high",
when: { recreatedBlocks: true },
note: "Versioning shows R unchanged and B1–B3 as moved, but Q's two copies as inserted by B and by A.",
},
{
severity: "high",
when: { recreatedBlocks: false },
note: "The diff also shows R and B1–B3 as deleted and inserted again: indenting and moving re-create blocks.",
},
{
Expand Down Expand Up @@ -1136,8 +1190,10 @@ export const scenarios: SuggestionScenario[] = [
kind: "concurrent",
id: "concurrent-parent-type-vs-child-edit",
feedback: [
lostEditNote("B"),
{
severity: "high",
when: { recreatedBlocks: false },
note: "The diff also shows Parent and Child as deleted and inserted again, all credited to A: changing the type re-creates blocks (see Change type of a parent block).",
},
{
Expand Down Expand Up @@ -1354,8 +1410,10 @@ export const scenarios: SuggestionScenario[] = [
kind: "concurrent",
id: "concurrent-text-vs-heading",
feedback: [
lostEditNote("A"),
{
severity: "high",
when: { recreatedBlocks: false },
note: "The diff shows the block as deleted and inserted again, all credited to B: changing the type re-creates it.",
},
{
Expand Down Expand Up @@ -1735,8 +1793,14 @@ export const scenarios: SuggestionScenario[] = [
kind: "single",
id: "remove-1-column",
feedback: [
{
severity: "info",
when: { recreatedBlocks: true },
note: "Versioning shows Left column as moved out of the columns, and the columns as deleted.",
},
{
severity: "high",
when: { recreatedBlocks: false },
note: "Removing the column re-creates Left column as a new block outside the columns. The diff therefore shows it as inserted, as if it were new, credited to whoever removed the column.",
},
],
Expand Down
19 changes: 17 additions & 2 deletions packages/core/src/editor/Block.css
Original file line number Diff line number Diff line change
Expand Up @@ -1122,15 +1122,30 @@ content span instead, using the `--user-color-*` properties that cascade down
from the wrapper. The `.bn-root ins, .bn-root del` rules above still style
serialized/static output, where the wrapper is a real, painted box.
*/
.bn-suggestion-mark {
/* A moved block's text keeps its authors, so it has no mark of its own: its
text element gets the inserted-text highlight instead. It shrinks to the text
(a flex item), or breaks per line in code blocks (an inline <code>). */
.bn-suggestion-mark,
ins[data-moved] > .bn-suggestion-node .bn-inline-content {
--bn-suggestion-token-color: currentColor;
background-color: color-mix(in srgb, var(--user-color-light) 50%, white);
color: var(--user-color-dark);
border-radius: 4px;
}

ins[data-moved] > .bn-suggestion-node .bn-inline-content {
box-decoration-break: clone;
-webkit-box-decoration-break: clone;
}

.dark.bn-root .bn-suggestion-mark,
.bn-block-content[data-content-type="codeBlock"] > pre .bn-suggestion-mark {
.dark.bn-root ins[data-moved] > .bn-suggestion-node .bn-inline-content,
.bn-block-content[data-content-type="codeBlock"] > pre .bn-suggestion-mark,
ins[data-moved]
> .bn-suggestion-node
.bn-block-content[data-content-type="codeBlock"]
> pre
.bn-inline-content {
background-color: color-mix(
in srgb,
var(--user-color-light) 25%,
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/i18n/locales/ar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,8 @@ export const ar: Dictionary = {
deleted_by: (users: string) => `حُذف بواسطة: ${users}`,
changed: "مُعدَّل",
changed_by: (users: string) => `عُدّل بواسطة: ${users}`,
moved: "تم النقل",
moved_by: (users: string) => `نقله: ${users}`,
formatting_change_by: (formats: string, users: string) =>
`تغيير التنسيق (${formats}) بواسطة: ${users}`,
},
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/i18n/locales/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,8 @@ export const de: Dictionary = {
deleted_by: (users: string) => `Gelöscht von: ${users}`,
changed: "Geändert",
changed_by: (users: string) => `Geändert von: ${users}`,
moved: "Verschoben",
moved_by: (users: string) => `Verschoben von: ${users}`,
formatting_change_by: (formats: string, users: string) =>
`Formatierungsänderung (${formats}) von: ${users}`,
},
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/i18n/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,8 @@ export const en = {
deleted_by: (users: string) => `Deleted by: ${users}`,
changed: "Changed",
changed_by: (users: string) => `Changed by: ${users}`,
moved: "Moved",
moved_by: (users: string) => `Moved by: ${users}`,
formatting_change_by: (formats: string, users: string) =>
`Formatting change (${formats}) by: ${users}`,
},
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/i18n/locales/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,8 @@ export const es: Dictionary = {
deleted_by: (users: string) => `Eliminado por: ${users}`,
changed: "Modificado",
changed_by: (users: string) => `Modificado por: ${users}`,
moved: "Movido",
moved_by: (users: string) => `Movido por: ${users}`,
formatting_change_by: (formats: string, users: string) =>
`Cambio de formato (${formats}) por: ${users}`,
},
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/i18n/locales/fa.ts
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,8 @@ export const fa = {
deleted_by: (users: string) => `حذف‌شده توسط: ${users}`,
changed: "تغییر\u200cیافته",
changed_by: (users: string) => `تغییر\u200cیافته توسط: ${users}`,
moved: "منتقل شد",
moved_by: (users: string) => `منتقل شده توسط: ${users}`,
formatting_change_by: (formats: string, users: string) =>
`تغییر قالب‌بندی (${formats}) توسط: ${users}`,
},
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/i18n/locales/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,8 @@ export const fr: Dictionary = {
deleted_by: (users: string) => `Supprimé par : ${users}`,
changed: "Modifié",
changed_by: (users: string) => `Modifié par : ${users}`,
moved: "Déplacé",
moved_by: (users: string) => `Déplacé par : ${users}`,
formatting_change_by: (formats: string, users: string) =>
`Modification de mise en forme (${formats}) par : ${users}`,
},
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/i18n/locales/he.ts
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,8 @@ export const he: Dictionary = {
deleted_by: (users: string) => `נמחק על ידי: ${users}`,
changed: "שונה",
changed_by: (users: string) => `שונה על ידי: ${users}`,
moved: "הועבר",
moved_by: (users: string) => `הועבר על ידי: ${users}`,
formatting_change_by: (formats: string, users: string) =>
`שינוי עיצוב (${formats}) על ידי: ${users}`,
},
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/i18n/locales/hr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,8 @@ export const hr: Dictionary = {
deleted_by: (users: string) => `Izbrisao/la: ${users}`,
changed: "Promijenjeno",
changed_by: (users: string) => `Promijenio/la: ${users}`,
moved: "Premješteno",
moved_by: (users: string) => `Premjestio: ${users}`,
formatting_change_by: (formats: string, users: string) =>
`Promjena oblikovanja (${formats}) od: ${users}`,
},
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/i18n/locales/is.ts
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,8 @@ export const is: Dictionary = {
deleted_by: (users: string) => `Eytt af: ${users}`,
changed: "Breytt",
changed_by: (users: string) => `Breytt af: ${users}`,
moved: "Fært",
moved_by: (users: string) => `Fært af: ${users}`,
formatting_change_by: (formats: string, users: string) =>
`Sniðbreyting (${formats}) af: ${users}`,
},
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/i18n/locales/it.ts
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,8 @@ export const it: Dictionary = {
deleted_by: (users: string) => `Eliminato da: ${users}`,
changed: "Modificato",
changed_by: (users: string) => `Modificato da: ${users}`,
moved: "Spostato",
moved_by: (users: string) => `Spostato da: ${users}`,
formatting_change_by: (formats: string, users: string) =>
`Modifica formattazione (${formats}) da: ${users}`,
},
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/i18n/locales/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,8 @@ export const ja: Dictionary = {
deleted_by: (users: string) => `削除者: ${users}`,
changed: "変更済み",
changed_by: (users: string) => `変更者: ${users}`,
moved: "移動済み",
moved_by: (users: string) => `移動者:${users}`,
formatting_change_by: (formats: string, users: string) =>
`書式の変更 (${formats}) 変更者: ${users}`,
},
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/i18n/locales/ko.ts
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,8 @@ export const ko: Dictionary = {
deleted_by: (users: string) => `삭제한 사람: ${users}`,
changed: "변경됨",
changed_by: (users: string) => `변경한 사람: ${users}`,
moved: "이동됨",
moved_by: (users: string) => `이동한 사용자: ${users}`,
formatting_change_by: (formats: string, users: string) =>
`서식 변경 (${formats}) 변경한 사람: ${users}`,
},
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/i18n/locales/nl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,8 @@ export const nl: Dictionary = {
deleted_by: (users: string) => `Verwijderd door: ${users}`,
changed: "Gewijzigd",
changed_by: (users: string) => `Gewijzigd door: ${users}`,
moved: "Verplaatst",
moved_by: (users: string) => `Verplaatst door: ${users}`,
formatting_change_by: (formats: string, users: string) =>
`Opmaakwijziging (${formats}) door: ${users}`,
},
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/i18n/locales/no.ts
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,8 @@ export const no: Dictionary = {
deleted_by: (users: string) => `Slettet av: ${users}`,
changed: "Endret",
changed_by: (users: string) => `Endret av: ${users}`,
moved: "Flyttet",
moved_by: (users: string) => `Flyttet av: ${users}`,
formatting_change_by: (formats: string, users: string) =>
`Formateringsendring (${formats}) av: ${users}`,
},
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/i18n/locales/pl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,8 @@ export const pl: Dictionary = {
deleted_by: (users: string) => `Usunięte przez: ${users}`,
changed: "Zmieniono",
changed_by: (users: string) => `Zmienione przez: ${users}`,
moved: "Przeniesiono",
moved_by: (users: string) => `Przeniesione przez: ${users}`,
formatting_change_by: (formats: string, users: string) =>
`Zmiana formatowania (${formats}) przez: ${users}`,
},
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/i18n/locales/pt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,8 @@ export const pt: Dictionary = {
deleted_by: (users: string) => `Excluído por: ${users}`,
changed: "Alterado",
changed_by: (users: string) => `Alterado por: ${users}`,
moved: "Movido",
moved_by: (users: string) => `Movido por: ${users}`,
formatting_change_by: (formats: string, users: string) =>
`Alteração de formatação (${formats}) por: ${users}`,
},
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/i18n/locales/ru.ts
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,8 @@ export const ru: Dictionary = {
deleted_by: (users: string) => `Удалено: ${users}`,
changed: "Изменено",
changed_by: (users: string) => `Изменено: ${users}`,
moved: "Перемещено",
moved_by: (users: string) => `Перемещено пользователем: ${users}`,
formatting_change_by: (formats: string, users: string) =>
`Изменение форматирования (${formats}): ${users}`,
},
Expand Down
Loading
Loading