Skip to content

Commit

Permalink
Unwrap paragraphs in LI
Browse files Browse the repository at this point in the history
  • Loading branch information
cammarosano authored and ged-odoo committed Mar 25, 2024
1 parent 4e49ee2 commit 0e7bb31
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 13 deletions.
19 changes: 15 additions & 4 deletions addons/html_editor/static/src/editor/list/list_plugin.js
Expand Up @@ -6,7 +6,14 @@ import { copyAttributes, removeClass, setTagName, toggleClass } from "../utils/d
import { isVisible } from "../utils/dom_info";
import { closestElement, descendants, getAdjacents } from "../utils/dom_traversal";
import { getTraversedBlocks } from "../utils/selection";
import { applyToTree, createList, getListMode, insertListAfter, mergeSimilarLists } from "./utils";
import {
applyToTree,
createList,
getListMode,
insertListAfter,
mergeSimilarLists,
unwrapParagraphInLI,
} from "./utils";

// @todo @phoenix: isFormatApplied for toolbar buttons should probably
// get a selection as parameter instead of the editable.
Expand Down Expand Up @@ -107,7 +114,7 @@ export class ListPlugin extends Plugin {
this.toggleList(payload.mode);
break;
case "NORMALIZE": {
this.mergeLists(payload.node);
this.normalize(payload.node);
break;
}
}
Expand Down Expand Up @@ -183,12 +190,16 @@ export class ListPlugin extends Plugin {
this.dispatch("ADD_STEP");
}

mergeLists(root = this.editable) {
normalize(root = this.editable) {
const closestNestedLI = closestElement(root, "li.oe-nested");
if (closestNestedLI) {
root = closestNestedLI;
}
applyToTree(root, mergeSimilarLists);
applyToTree(root, (element) => {
element = mergeSimilarLists(element);
element = unwrapParagraphInLI(element);
return element;
});
}

// --------------------------------------------------------------------------
Expand Down
16 changes: 16 additions & 0 deletions addons/html_editor/static/src/editor/list/utils.js
@@ -1,3 +1,4 @@
import { unwrapContents } from "../utils/dom";
import { getAdjacents } from "../utils/dom_traversal";
import { preserveCursor } from "../utils/selection";

Expand Down Expand Up @@ -70,6 +71,7 @@ function compareListTypes(a, b) {
return true;
}

// @todo @phoenix: use the selection plugin to preserve the cursor
export function mergeSimilarLists(element) {
if (!element.matches("ul, ol, li.oe-nested")) {
return element;
Expand All @@ -80,6 +82,20 @@ export function mergeSimilarLists(element) {
return mergedList;
}

// @todo @phoenix: use the selection plugin to preserve the cursor
// @todo @phoenix: wrap P in a span if P has classes (mind the oe-hint class)
export function unwrapParagraphInLI(element) {
if (!element.matches("li > p")) {
return element;
}
const parentLI = element.parentElement;
const restoreCursor = preserveCursor(element.ownerDocument);
const contents = unwrapContents(element);
restoreCursor(new Map([element, parentLI]));
// This assumes an empty P has at least one child (BR).
return contents[0];
}

export function applyToTree(root, func) {
const modifiedRoot = func(root);
let next = modifiedRoot.firstElementChild;
Expand Down
Expand Up @@ -45,7 +45,7 @@ describe("Selection collapsed", () => {
});
});

test.todo("should remove the only character in a list", async () => {
test("should remove the only character in a list", async () => {
await testEditor({
contentBefore: "<ol><li>a[]</li></ol>",
stepFunction: deleteBackward,
Expand Down Expand Up @@ -405,7 +405,7 @@ describe("Selection collapsed", () => {
});
});

test.todo("should remove the only character in a list", async () => {
test("should remove the only character in a list", async () => {
await testEditor({
contentBefore: "<ul><li>a[]</li></ul>",
stepFunction: deleteBackward,
Expand Down Expand Up @@ -796,7 +796,7 @@ describe("Selection collapsed", () => {
});
});

test.todo("should remove the only character in a list", async () => {
test("should remove the only character in a list", async () => {
await testEditor({
removeCheckIds: true,
contentBefore: '<ul class="o_checklist"><li class="o_checked">a[]</li></ul>',
Expand Down Expand Up @@ -1357,7 +1357,7 @@ describe("Selection collapsed", () => {
});
describe("Mixed", () => {
describe("Ordered to unordered", () => {
test.todo("should merge an ordered list into an unordered list", async () => {
test("should merge an ordered list into an unordered list", async () => {
await testEditor({
contentBefore: "<ul><li>a</li></ul><ol><li>[]b</li></ol>",
stepFunction: async (editor) => {
Expand Down Expand Up @@ -1467,7 +1467,7 @@ describe("Selection collapsed", () => {
});
});
describe("Unordered to ordered", () => {
test.todo("should merge an unordered list into an ordered list", async () => {
test("should merge an unordered list into an ordered list", async () => {
await testEditor({
contentBefore: "<ol><li>a</li></ol><ul><li>[]b</li></ul>",
stepFunction: async (editor) => {
Expand Down Expand Up @@ -1595,7 +1595,7 @@ describe("Selection collapsed", () => {
});
});
describe("Checklist to unordered", () => {
test.todo("should merge an checklist list into an unordered list", async () => {
test("should merge an checklist list into an unordered list", async () => {
await testEditor({
contentBefore: '<ul><li>a</li></ul><ul class="o_checklist"><li>[]b</li></ul>',
stepFunction: async (editor) => {
Expand Down Expand Up @@ -1716,7 +1716,7 @@ describe("Selection collapsed", () => {
});
});
describe("Unordered to checklist", () => {
test.todo("should merge an unordered list into an checklist list", async () => {
test("should merge an unordered list into an checklist list", async () => {
await testEditor({
removeCheckIds: true,
contentBefore:
Expand Down
Expand Up @@ -54,7 +54,7 @@ describe("Selection collapsed", () => {
});
});

test.todo("should remove the only character in a list", async () => {
test("should remove the only character in a list", async () => {
await testEditor({
contentBefore: "<ul><li>[]a</li></ul>",
stepFunction: deleteForward,
Expand Down Expand Up @@ -255,7 +255,7 @@ describe("Selection collapsed", () => {
});
});

test.todo("should remove the only character in a checklist", async () => {
test("should remove the only character in a checklist", async () => {
await testEditor({
removeCheckIds: true,
contentBefore: '<ul class="o_checklist"><li class="o_checked">[]a</li></ul>',
Expand Down

0 comments on commit 0e7bb31

Please sign in to comment.