Skip to content

Commit

Permalink
fix: depth issues in BulletedList with md serialize/deserialize; closes
Browse files Browse the repository at this point in the history
  • Loading branch information
gloaysa committed Oct 12, 2024
1 parent 67365a6 commit 4eeeee4
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 28 deletions.
1 change: 1 addition & 0 deletions packages/core/editor/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export { findPluginBlockBySelectionPath } from './utils/findPluginBlockBySelecti
export { findSlateBySelectionPath } from './utils/findSlateBySelectionPath';
export { findPluginBlockByType } from './utils/findPluginBlockByType';
export { deserializeTextNodes } from './parsers/deserializeTextNodes';
export { deserializeListNodes } from './parsers/deserializeListNodes';
export { serializeTextNodes, serializeTextNodesIntoMarkdown } from './parsers/serializeTextNodes';

export { createYooptaEditor } from './editor';
Expand Down
50 changes: 50 additions & 0 deletions packages/core/editor/src/parsers/deserializeListNodes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import {Descendant} from 'slate';
import {SlateElement, YooEditor} from '../editor/types';
import {generateId} from '../utils/generateId';

type ListElement = HTMLUListElement | HTMLOListElement | Element

export function deserializeListNodes(editor: YooEditor, listElement: ListElement): Descendant[] {
const deserializedNodes: Descendant[] = [];

if (listElement.nodeName === 'UL' || listElement.nodeName === 'OL') {
const listItems = Array.from(listElement.children).filter(el => el.nodeName === 'LI');

listItems.forEach((item) => {
const listItemChildren: Descendant[] = [];
const itemText = item.childNodes[0]?.textContent?.trim() ?? '';

const isTodoListItem = /\[\s*\S?\s*\]/.test(itemText);

if (isTodoListItem) {
console.log('isTodoListItem', itemText);
return;
}

if (itemText.length > 0) {
listItemChildren.push({ text: itemText, });
} else {
// Don't like this, but I was getting an error when it was empty
listItemChildren.push({ text: '' });
}

const nestedList = item.querySelector('ul, ol');
if (nestedList) {
const nestedListNodes = deserializeListNodes(editor, nestedList);
listItemChildren.push({
id: generateId(),
children: nestedListNodes,
} as SlateElement);
}

deserializedNodes.push({
id: generateId(),
type: listElement.nodeName === 'UL' ? 'bulleted-list' : 'ordered-list',
children: listItemChildren,
props: { nodeType: 'block' }
} as SlateElement);
});
}

return deserializedNodes;
}
2 changes: 0 additions & 2 deletions packages/core/exports/src/html/deserialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,6 @@ export function deserializeHTML(editor: YooEditor, htmlString: string): YooptaCo
const parsedHtml = new DOMParser().parseFromString(htmlString, 'text/html');
const value: YooptaContentValue = {};

console.log('parsedHtml.body', parsedHtml.body);

const PLUGINS_NODE_NAME_MATCHERS_MAP = getMappedPluginByNodeNames(editor);
const blocks = deserialize(editor, PLUGINS_NODE_NAME_MATCHERS_MAP, parsedHtml.body)
.flat()
Expand Down
34 changes: 8 additions & 26 deletions packages/plugins/lists/src/plugin/BulletedList.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {
buildBlockData,
deserializeTextNodes,
deserializeListNodes,
generateId,
serializeTextNodes,
serializeTextNodesIntoMarkdown,
Expand Down Expand Up @@ -36,35 +36,17 @@ const BulletedList = new YooptaPlugin<Pick<ListElementMap, 'bulleted-list'>>({
nodeNames: ['UL'],
parse(el, editor) {
if (el.nodeName === 'UL') {
const listItems = el.querySelectorAll('li');

const align = (el.getAttribute('data-meta-align') || 'left') as YooptaBlockData['meta']['align'];
const depth = parseInt(el.getAttribute('data-meta-depth') || '0', 10);

const bulletListBlocks: YooptaBlockData[] = Array.from(listItems)
.filter((listItem) => {
const textContent = listItem.textContent || '';
const isTodoListItem = /\[\s*\S?\s*\]/.test(textContent);

return !isTodoListItem;
})
.map((listItem) => {
return buildBlockData({
id: generateId(),
type: 'BulletedList',
value: [
{
id: generateId(),
type: 'bulleted-list',
children: deserializeTextNodes(editor, listItem.childNodes),
props: { nodeType: 'block' },
},
],
meta: { order: 0, depth: depth, align },
});
});
const deserializedList = deserializeListNodes(editor, el);

if (bulletListBlocks.length > 0) return bulletListBlocks;
return [buildBlockData({
id: generateId(),
type: 'BulletedList',
value: deserializedList,
meta: { order: 0, depth: depth, align },
})]
}
},
},
Expand Down

0 comments on commit 4eeeee4

Please sign in to comment.