Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update lexical to v0.13.1 #1079

Merged
merged 19 commits into from
Feb 6, 2024
Merged
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
2 changes: 2 additions & 0 deletions packages/kg-default-nodes/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
cjs/
es/
build/
tsconfig.tsbuildinfo
4 changes: 4 additions & 0 deletions packages/kg-default-nodes/lib/nodes/ExtendedTextNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ export class ExtendedTextNode extends TextNode {
this.__mode === 0
);
}

isInline() {
return true;
}
}

function patchConversion(originalDOMConverter, convertFn) {
Expand Down
14 changes: 7 additions & 7 deletions packages/kg-default-nodes/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@
"devDependencies": {
"@babel/eslint-parser": "^7.19.1",
"@babel/plugin-syntax-import-assertions": "^7.20.0",
"@lexical/headless": "0.12.2",
"@lexical/html": "0.12.2",
"@lexical/headless": "0.13.1",
"@lexical/html": "0.13.1",
"@prettier/sync": "^0.3.0",
"@rollup/plugin-babel": "6.0.4",
"c8": "9.1.0",
Expand All @@ -44,15 +44,15 @@
"sinon": "17.0.1"
},
"dependencies": {
"@lexical/clipboard": "0.12.2",
"@lexical/rich-text": "0.12.2",
"@lexical/selection": "0.12.2",
"@lexical/utils": "0.12.2",
"@lexical/clipboard": "0.13.1",
"@lexical/rich-text": "0.13.1",
"@lexical/selection": "0.13.1",
"@lexical/utils": "0.13.1",
"@tryghost/kg-clean-basic-html": "^4.0.3",
"@tryghost/kg-markdown-html-renderer": "^7.0.2",
"html-minifier": "^4.0.0",
"jsdom": "^23.0.0",
"lexical": "0.12.2",
"lexical": "0.13.1",
"lodash": "^4.17.21",
"luxon": "^3.3.0"
}
Expand Down
12 changes: 6 additions & 6 deletions packages/kg-default-transforms/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,19 @@
"access": "public"
},
"devDependencies": {
"@lexical/headless": "0.12.2",
"@lexical/link": "0.12.2",
"@lexical/headless": "0.13.1",
"@lexical/link": "0.13.1",
"c8": "9.1.0",
"mocha": "10.2.0",
"sinon": "17.0.1",
"ts-node": "10.9.2",
"typescript": "5.3.3"
},
"dependencies": {
"@lexical/list": "0.12.2",
"@lexical/rich-text": "0.12.2",
"@lexical/utils": "0.12.2",
"@lexical/list": "0.13.1",
"@lexical/rich-text": "0.13.1",
"@lexical/utils": "0.13.1",
"@tryghost/kg-default-nodes": "^1.0.7",
"lexical": "0.12.2"
"lexical": "0.13.1"
}
}
2 changes: 1 addition & 1 deletion packages/kg-default-transforms/src/default-transforms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export function registerDefaultTransforms(editor: LexicalEditor) {
// fix invalid nesting of nodes
registerDenestTransform(editor, ParagraphNode, () => ($createParagraphNode())),
registerDenestTransform(editor, HeadingNode, node => ($createHeadingNode(node.getTag()))),
registerDenestTransform(editor, ExtendedHeadingNode, node => ($createHeadingNode(node.getTag()))),
registerDenestTransform(editor, ExtendedHeadingNode, (node: ExtendedHeadingNode) => ($createHeadingNode(node.getTag()))),
registerDenestTransform(editor, QuoteNode, () => ($createQuoteNode())),
registerDenestTransform(editor, ListNode, node => ($createListNode(node.getListType(), node.getStart()))),
registerDenestTransform(editor, ListItemNode, () => ($createListItemNode())),
Expand Down
7 changes: 5 additions & 2 deletions packages/kg-default-transforms/src/transforms/denest.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {$isListItemNode, $isListNode} from '@lexical/list';
import {ElementNode, $createParagraphNode, LexicalEditor, LexicalNode, Klass, $getRoot, $isRootNode} from 'lexical';
import {ElementNode, $createParagraphNode, LexicalEditor, LexicalNode, Klass, $getRoot, $isRootNode, $isTextNode, $isLineBreakNode} from 'lexical';

export type CreateNodeFn<T extends LexicalNode> = (originalNode: T) => T;

Expand Down Expand Up @@ -43,6 +43,9 @@ function $isInvalidListItemNode(node: LexicalNode) {
// non-inline nodes can only exist at top-level inside a root node
// ignore list and list item nodes because they aren't inline but can be nested inside each other
function $isInvalidChildNode(node: LexicalNode) {
if ($isLineBreakNode(node) || $isTextNode(node)) { // line break and text nodes don't have an isInline method
return false;
}
return $isInvalidListNode(node)
|| $isInvalidListItemNode(node)
|| node.isInline && !node.isInline() && !$isListNode(node) && !$isListItemNode(node);
Expand Down Expand Up @@ -97,7 +100,7 @@ export function denestTransform<T extends ElementNode>(node: T, createNode: Crea
// meaning first child needs to be inserted last to maintain order.
tempParagraph.getChildren().reverse().forEach((child) => {
// ensure we don't add list items directly into root node
// TODO: can we handle this elsewhere/more genericly?
// TODO: can we handle this elsewhere/more generically?
if ($isRootNode(parent.getParent()) && $isListItemNode(child)) {
const paragraphNode = $createParagraphNode();
paragraphNode.append(...child.getChildren());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import {$isListNode, ListNode} from '@lexical/list';
import {LexicalEditor, LexicalNode} from 'lexical';
import {LexicalEditor} from 'lexical';

export function mergeListNodesTransform(node: LexicalNode) {
export function mergeListNodesTransform(node: ListNode) {
const nextSibling = node.getNextSibling();

if ($isListNode(nextSibling) && nextSibling.getListType() === node.getListType()) {
if ($isListNode(nextSibling) && $isListNode(node) && nextSibling.getListType() === node.getListType()) {
node.append(...nextSibling.getChildren());
nextSibling.remove();
}
Expand Down
6 changes: 5 additions & 1 deletion packages/kg-default-transforms/src/typings.d.ts
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
declare module '@tryghost/kg-default-nodes';
declare module '@tryghost/kg-default-nodes' {
import {DEFAULT_NODES, ExtendedHeadingNode, ImageNode} from '@tryghost/kg-default-nodes';

export {DEFAULT_NODES, ExtendedHeadingNode, ImageNode};
};
4 changes: 2 additions & 2 deletions packages/kg-default-transforms/test/transforms/denest.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ describe('Denest transform', function () {
const registerTransforms = (editor: LexicalEditor) => {
registerDenestTransform(editor, ParagraphNode, () => ($createParagraphNode()));
registerDenestTransform(editor, HeadingNode, node => ($createHeadingNode(node.getTag())));
registerDenestTransform(editor, ExtendedHeadingNode, node => ($createHeadingNode(node.getTag())));
registerDenestTransform(editor, ExtendedHeadingNode, (node: ExtendedHeadingNode) => ($createHeadingNode(node.getTag())));
registerDenestTransform(editor, ListNode, node => ($createListNode(node.getListType(), node.getStart())));
registerDenestTransform(editor, ListItemNode, () => ($createListItemNode()));
};
Expand Down Expand Up @@ -880,7 +880,7 @@ describe('Denest transform', function () {
const registerTransforms = (editor: LexicalEditor) => {
registerDenestTransform(editor, ParagraphNode, () => ($createParagraphNode()));
registerDenestTransform(editor, HeadingNode, node => ($createHeadingNode(node.getTag())));
registerDenestTransform(editor, ExtendedHeadingNode, node => ($createHeadingNode(node.getTag())));
registerDenestTransform(editor, ExtendedHeadingNode, (node: ExtendedHeadingNode) => ($createHeadingNode(node.getTag())));
registerDenestTransform(editor, ListNode, node => ($createListNode(node.getListType(), node.getStart())));
registerDenestTransform(editor, ListItemNode, () => ($createListItemNode()));
};
Expand Down
14 changes: 7 additions & 7 deletions packages/kg-html-to-lexical/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@
"typescript": "5.3.3"
},
"dependencies": {
"@lexical/clipboard": "0.12.2",
"@lexical/headless": "0.12.2",
"@lexical/html": "0.12.2",
"@lexical/link": "0.12.2",
"@lexical/list": "0.12.2",
"@lexical/rich-text": "0.12.2",
"@lexical/clipboard": "0.13.1",
"@lexical/headless": "0.13.1",
"@lexical/html": "0.13.1",
"@lexical/link": "0.13.1",
"@lexical/list": "0.13.1",
"@lexical/rich-text": "0.13.1",
"@tryghost/kg-default-nodes": "^1.0.7",
"@tryghost/kg-default-transforms": "^1.0.8",
"jsdom": "^23.0.0",
"lexical": "0.12.2"
"lexical": "0.13.1"
}
}
6 changes: 5 additions & 1 deletion packages/kg-lexical-html-renderer/lib/LexicalHTMLRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,11 @@ export default class LexicalHTMLRenderer {

// fetch dynamic data
const renderData = new Map();
await Promise.all(dynamicDataNodes.map(async (node: LexicalNode) => {
await Promise.all(dynamicDataNodes.map(async (node) => {
if (!node.getDynamicData) {
return;
}

const {key, data} = await node.getDynamicData(options);
renderData.set(key, data);
}));
Expand Down
34 changes: 16 additions & 18 deletions packages/kg-lexical-html-renderer/lib/convert-to-html-string.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,10 @@
import {ElementNode, LexicalNode} from 'lexical';
import {$getRoot, $isElementNode, $isLineBreakNode, $isParagraphNode, $isTextNode} from 'lexical';
import {$isLinkNode} from '@lexical/link';
// TODO: update once kg-default-nodes is typescript
// eslint-disable-next-line @typescript-eslint/no-var-requires
const {$isKoenigCard, KoenigDecoratorNode} = require('@tryghost/kg-default-nodes');
import {$isKoenigCard, RendererOptions} from '@tryghost/kg-default-nodes';
import TextContent from './utils/TextContent';
import elementTransformers from './transformers';

export interface RendererOptions {
usedIdAttributes?: Record<string, number>;
dom?: import('jsdom').JSDOM,
type?: 'inner' | 'outer' | 'value'
}

export default function $convertToHtmlString(options: RendererOptions = {}): string {
const output: string[] = [];
const children: LexicalNode[] = $getRoot().getChildren();
Expand All @@ -37,7 +29,7 @@ export default function $convertToHtmlString(options: RendererOptions = {}): str
return output.join('');
}

function exportTopLevelElementOrDecorator(node: LexicalNode | typeof KoenigDecoratorNode, options: RendererOptions): string | null {
function exportTopLevelElementOrDecorator(node: LexicalNode, options: RendererOptions): string | null {
if ($isKoenigCard(node)) {
// NOTE: kg-default-nodes appends type in rare cases to make use of this functionality... with moving to typescript,
// we should change this implementation because it's confusing, or we should override the DOMExportOutput type
Expand All @@ -47,27 +39,33 @@ function exportTopLevelElementOrDecorator(node: LexicalNode | typeof KoenigDecor
case 'inner':
return element.innerHTML;
case 'value':
return element.value;
if ('value' in element) {
return element.value;
}

return '';
default:
return element.outerHTML;
}
}

// note: unsure why this type isn't being picked up from the import
for (const transformer of elementTransformers) {
if (transformer.export !== null) {
const result = transformer.export(node, options, _node => exportChildren(_node, options));
if ($isElementNode(node)) {
// note: unsure why this type isn't being picked up from the import
for (const transformer of elementTransformers) {
if (transformer.export !== null) {
const result = transformer.export(node, options, _node => exportChildren(_node, options));

if (result !== null) {
return result;
if (result !== null) {
return result;
}
}
}
}

return $isElementNode(node) ? exportChildren(node, options) : null;
}

function exportChildren(node: ElementNode | LexicalNode, options: RendererOptions): string {
function exportChildren(node: ElementNode, options: RendererOptions): string {
const output = [];
const children = node.getChildren();

Expand Down
16 changes: 7 additions & 9 deletions packages/kg-lexical-html-renderer/lib/get-dynamic-data-nodes.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
import type {EditorState, LexicalNode} from 'lexical';

import {$getRoot} from 'lexical';
// TODO: update to import when this is moved to typescript
// eslint-disable-next-line @typescript-eslint/no-var-requires
const {$isKoenigCard} = require('@tryghost/kg-default-nodes');
import {$isKoenigCard, KoenigDecoratorNode} from '@tryghost/kg-default-nodes';

import type {EditorState} from 'lexical';

export default function getDynamicDataNodes(editorState: EditorState) {
const dynamicNodes: LexicalNode[] = [];
export default function getDynamicDataNodes(editorState: EditorState): KoenigDecoratorNode[] {
const dynamicNodes: KoenigDecoratorNode[] = [];

editorState.read(() => {
const root = $getRoot();
const nodes = root.getChildren();

nodes.forEach((node: LexicalNode) => {
nodes.forEach((node) => {
if ($isKoenigCard(node) && node.hasDynamicData?.()) {
dynamicNodes.push(node);
}
});
});

return dynamicNodes;
}
}
27 changes: 27 additions & 0 deletions packages/kg-lexical-html-renderer/lib/kg-default-nodes.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
declare module '@tryghost/kg-default-nodes' {
import {LexicalNode, DecoratorNode, LexicalEditor, ElementNode} from 'lexical';
import * as KgDefaultNodes from '@tryghost/kg-default-nodes';

export interface RendererOptions {
usedIdAttributes?: Record<string, number>;
dom?: import('jsdom').JSDOM,
type?: 'inner' | 'outer' | 'value'
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type X = any;

export class KoenigDecoratorNode extends DecoratorNode<X> {
// TODO: exportDOM override isn't directly compatible with base class, should fix when converting kg-default-nodes
exportDOM(options: LexicalEditor | RendererOptions): {
element: HTMLElement | HTMLInputElement | HTMLTextAreaElement;
type: 'inner' | 'outer' | 'value'
};
hasDynamicData?(): boolean;
getDynamicData?(options: RendererOptions): Promise<{key: number; data: unknown}>;
}
export function $isKoenigCard(node: LexicalNode): node is KgDefaultNodes.KoenigDecoratorNode;

export class AsideNode extends ElementNode {}
export function $isAsideNode(node: LexicalNode): node is KgDefaultNodes.AsideNode;
}
3 changes: 3 additions & 0 deletions packages/kg-lexical-html-renderer/lib/kg-utils.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
declare module '@tryghost/kg-utils' {
export function slugify (text: string, options?: {ghostVersion?: string, type?: string}): string;
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
// TODO: update this to an import once we move kg-default-nodes to typescript
// eslint-disable-next-line @typescript-eslint/no-var-requires
const {$isAsideNode} = require('@tryghost/kg-default-nodes');
import type {LexicalNode} from 'lexical';
import {$isAsideNode, RendererOptions} from '@tryghost/kg-default-nodes';
import type {ElementNode} from 'lexical';
import type {ExportChildren} from '..';
import type {RendererOptions} from '../../convert-to-html-string';

module.exports = {
export(node: LexicalNode, options: RendererOptions, exportChildren: ExportChildren) {
export(node: ElementNode, options: RendererOptions, exportChildren: ExportChildren) {
if (!$isAsideNode(node)) {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import {$isQuoteNode} from '@lexical/rich-text';
import type {LexicalNode} from 'lexical';
import type {RendererOptions} from '@tryghost/kg-default-nodes';
import type {ElementNode} from 'lexical';
import type {ExportChildren} from '..';
import type {RendererOptions} from '../../convert-to-html-string';

module.exports = {
export(node: LexicalNode, options: RendererOptions, exportChildren: ExportChildren) {
export(node: ElementNode, options: RendererOptions, exportChildren: ExportChildren) {
if (!$isQuoteNode(node)) {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import {$isHeadingNode} from '@lexical/rich-text';
import generateId from '../../utils/generate-id';
import type {LexicalNode} from 'lexical';
import type {RendererOptions} from '@tryghost/kg-default-nodes';
import type {ElementNode} from 'lexical';
import type {ExportChildren} from '..';
import type {RendererOptions} from '../../convert-to-html-string';

module.exports = {
export(node: LexicalNode, options: RendererOptions, exportChildren: ExportChildren) {
export(node: ElementNode, options: RendererOptions, exportChildren: ExportChildren) {
if (!$isHeadingNode(node)) {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import {$isListNode, $isListItemNode} from '@lexical/list';
import type {LexicalNode} from 'lexical';
import type {ElementNode} from 'lexical';
import type {ListNode} from '@lexical/list';
import type {RendererOptions} from '@tryghost/kg-default-nodes';
import type {ExportChildren} from '..';
import type {RendererOptions} from '../../convert-to-html-string';

const exportList = function (node: LexicalNode, options: RendererOptions, exportChildren: ExportChildren): string | null {
const exportList = function (node: ElementNode, options: RendererOptions, exportChildren: ExportChildren): string | null {
if (!$isListNode(node)) {
return null;
}
Expand All @@ -20,7 +21,7 @@ const exportList = function (node: LexicalNode, options: RendererOptions, export
// </li>
let liOpen = false;

const exportListContent = (listNode: LexicalNode): string => {
const exportListContent = (listNode: ListNode): string => {
const output = [];
const children = listNode.getChildren();

Expand Down Expand Up @@ -66,7 +67,7 @@ const exportList = function (node: LexicalNode, options: RendererOptions, export
};

module.exports = {
export(node: LexicalNode, options: RendererOptions, exportChildren: ExportChildren) {
export(node: ElementNode, options: RendererOptions, exportChildren: ExportChildren) {
return exportList(node, options, exportChildren);
}
};
Loading
Loading