Skip to content
Open
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
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
{
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.addMissingImports": "explicit"
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fyi, this makes sure missing imports are added automatically on save, I kept finding myself to do this manually (or AI-powered)

},
"[javascript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,21 @@ import {
BlockIdentifier,
BlockSchema,
InlineContentSchema,
partialBlockToFullBlock,
StyleSchema,
} from "../../../../schema/index.js";
import { blockToNode } from "../../../nodeConversions/blockToNode.js";
import { nodeToBlock } from "../../../nodeConversions/nodeToBlock.js";
import { getNodeById } from "../../../nodeUtil.js";
import { getPmSchema } from "../../../pmUtil.js";
import { getBlockNoteSchema, getPmSchema } from "../../../pmUtil.js";

export function insertBlocks<
BSchema extends BlockSchema,
I extends InlineContentSchema,
S extends StyleSchema,
>(
tr: Transaction,
// TBD: allow PartialBlock here?
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could move it a layer up to the BlockNoteEditor (and only allow partials there, not in the commands. However, for updateBlock I don't think that's feasible, so maybe better to keep it here

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These don't get run anywhere but from the editor instance, so imo it doesn't make too much a difference anyway

blocksToInsert: PartialBlock<BSchema, I, S>[],
referenceBlock: BlockIdentifier,
placement: "before" | "after" = "before",
Expand All @@ -27,7 +29,10 @@ export function insertBlocks<
typeof referenceBlock === "string" ? referenceBlock : referenceBlock.id;
const pmSchema = getPmSchema(tr);
const nodesToInsert = blocksToInsert.map((block) =>
blockToNode(block, pmSchema),
blockToNode(
partialBlockToFullBlock(getBlockNoteSchema(pmSchema), block),
pmSchema,
),
);

const posInfo = getNodeById(id, tr.doc);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
Transaction,
} from "prosemirror-state";
import { CellSelection } from "prosemirror-tables";

import { Block } from "../../../../blocks/defaultBlocks.js";
import type { BlockNoteEditor } from "../../../../editor/BlockNoteEditor";
import { BlockIdentifier } from "../../../../schema/index.js";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import type { Node } from "prosemirror-model";
import type { Transaction } from "prosemirror-state";
import type { Block, PartialBlock } from "../../../../blocks/defaultBlocks.js";
import type {
BlockIdentifier,
BlockSchema,
InlineContentSchema,
StyleSchema,
import {
partialBlockToFullBlock,
type BlockIdentifier,
type BlockSchema,
type InlineContentSchema,
type StyleSchema,
} from "../../../../schema/index.js";
import { blockToNode } from "../../../nodeConversions/blockToNode.js";
import { nodeToBlock } from "../../../nodeConversions/nodeToBlock.js";
import { getPmSchema } from "../../../pmUtil.js";
import { getBlockNoteSchema, getPmSchema } from "../../../pmUtil.js";

export function removeAndInsertBlocks<
BSchema extends BlockSchema,
Expand All @@ -18,6 +19,7 @@ export function removeAndInsertBlocks<
>(
tr: Transaction,
blocksToRemove: BlockIdentifier[],
// TBD: allow PartialBlock here?
blocksToInsert: PartialBlock<BSchema, I, S>[],
): {
insertedBlocks: Block<BSchema, I, S>[];
Expand All @@ -27,7 +29,10 @@ export function removeAndInsertBlocks<
// Converts the `PartialBlock`s to ProseMirror nodes to insert them into the
// document.
const nodesToInsert: Node[] = blocksToInsert.map((block) =>
blockToNode(block, pmSchema),
blockToNode(
partialBlockToFullBlock(getBlockNoteSchema(pmSchema), block),
pmSchema,
),
);

const idsOfBlocksToRemove = new Set<string>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ import type {
BlockSchema,
} from "../../../../schema/blocks/types.js";
import type { InlineContentSchema } from "../../../../schema/inlineContent/types.js";
import {
partialBlockToFullBlock,
partialInlineContentToInlineContent,
partialTableContentToTableContent,
} from "../../../../schema/partialBlockToFullBlock.js";
import type { StyleSchema } from "../../../../schema/styles/types.js";
import { UnreachableCaseError } from "../../../../util/typescript.js";
import {
Expand All @@ -27,7 +32,7 @@ import {
} from "../../../nodeConversions/blockToNode.js";
import { nodeToBlock } from "../../../nodeConversions/nodeToBlock.js";
import { getNodeById } from "../../../nodeUtil.js";
import { getPmSchema } from "../../../pmUtil.js";
import { getBlockNoteSchema, getPmSchema } from "../../../pmUtil.js";

// for compatibility with tiptap. TODO: remove as we want to remove dependency on tiptap command interface
export const updateBlockCommand = <
Expand Down Expand Up @@ -71,7 +76,7 @@ export function updateBlockTr<
}

const pmSchema = getPmSchema(tr);

const schema = getBlockNoteSchema<BSchema, I, S>(pmSchema);
if (
replaceFromPos !== undefined &&
replaceToPos !== undefined &&
Expand Down Expand Up @@ -127,17 +132,19 @@ export function updateBlockTr<
// currently, we calculate the new node and replace the entire node with the desired new node.
// for this, we do a nodeToBlock on the existing block to get the children.
// it would be cleaner to use a ReplaceAroundStep, but this is a bit simpler and it's quite an edge case
const existingBlock = nodeToBlock(blockInfo.bnBlock.node, pmSchema);
const newFullBlock = partialBlockToFullBlock(schema, block);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const newFullBlock = partialBlockToFullBlock(schema, block);
const newBlock = partialBlockToFullBlock(schema, block);

There are partial blocks & blocks. Full block gives a third name which is not helpful

if (block.children === undefined) {
// if no children are passed in, use existing children
const existingBlock = nodeToBlock<BSchema, I, S>(
blockInfo.bnBlock.node,
pmSchema,
);
newFullBlock.children = existingBlock.children;
}
tr.replaceWith(
blockInfo.bnBlock.beforePos,
blockInfo.bnBlock.afterPos,
blockToNode(
{
children: existingBlock.children, // if no children are passed in, use existing children
...block,
},
pmSchema,
),
blockToNode(newFullBlock, pmSchema),
);

return;
Expand Down Expand Up @@ -174,6 +181,7 @@ function updateBlockContentNode<
replaceToOffset?: number,
) {
const pmSchema = getPmSchema(tr);
const schema = getBlockNoteSchema<BSchema, I, S>(pmSchema);
let content: PMNode[] | "keep" = "keep";

// Has there been any custom content provided?
Expand All @@ -188,9 +196,22 @@ function updateBlockContentNode<
} else if (Array.isArray(block.content)) {
// Adds a text node with the provided styles converted into marks to the content,
// for each InlineContent object.
content = inlineContentToNodes(block.content, pmSchema, newNodeType.name);
content = inlineContentToNodes(
partialInlineContentToInlineContent(
block.content,
schema.inlineContentSchema,
),
pmSchema,
newNodeType.name,
);
} else if (block.content.type === "tableContent") {
content = tableContentToNodes(block.content, pmSchema);
content = tableContentToNodes(
partialTableContentToTableContent(
block.content,
schema.inlineContentSchema,
),
pmSchema,
);
} else {
throw new UnreachableCaseError(block.content.type);
}
Expand Down Expand Up @@ -276,9 +297,10 @@ function updateChildren<
S extends StyleSchema,
>(block: PartialBlock<BSchema, I, S>, tr: Transform, blockInfo: BlockInfo) {
const pmSchema = getPmSchema(tr);
const schema = getBlockNoteSchema<BSchema, I, S>(pmSchema);
if (block.children !== undefined && block.children.length > 0) {
const childNodes = block.children.map((child) => {
return blockToNode(child, pmSchema);
return blockToNode(partialBlockToFullBlock(schema, child), pmSchema);
});

// Checks if a blockGroup node already exists.
Expand Down
36 changes: 17 additions & 19 deletions packages/core/src/api/blockManipulation/tables/tables.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { DefaultBlockSchema } from "../../../blocks/defaultBlocks.js";
import {
BlockFromConfigNoChildren,
PartialTableContent,
TableCell,
TableContent,
} from "../../../schema/blocks/types.js";
import {
type BlockFromConfig,
type PartialTableContent,
type TableCell,
type TableContent,
isPartialLinkInlineContent,
isStyledTextInlineContent,
} from "../../../schema/index.js";
Expand Down Expand Up @@ -185,7 +183,7 @@ type OccupancyGrid = (RelativeCellIndices & {
* @returns an {@link OccupancyGrid}
*/
export function getTableCellOccupancyGrid(
block: BlockFromConfigNoChildren<DefaultBlockSchema["table"], any, any>,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stopped exporting BlockFromConfigNoChildren so we have more consistency in the codebase

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While we are cleaning up types, I believe that:

BlockFromConfig<DefaultBlockSchema["table"], any, any>

Should only be:

BlockFromConfig<DefaultBlockSchema["table"]>

Most of the time we don't care about the other parameters, and have to remove their defaults with any. This goes for most instances of B, I, S

block: BlockFromConfig<DefaultBlockSchema["table"], any, any>,
): OccupancyGrid {
const { height, width } = getDimensionsOfTable(block);

Expand Down Expand Up @@ -295,7 +293,7 @@ export function getAbsoluteTableCells(
/**
* The table block containing the cell.
*/
block: BlockFromConfigNoChildren<DefaultBlockSchema["table"], any, any>,
block: BlockFromConfig<DefaultBlockSchema["table"], any, any>,
/**
* The occupancy grid of the table.
*/
Expand Down Expand Up @@ -327,7 +325,7 @@ export function getAbsoluteTableCells(
* @returns The height and width of the table.
*/
export function getDimensionsOfTable(
block: BlockFromConfigNoChildren<DefaultBlockSchema["table"], any, any>,
block: BlockFromConfig<DefaultBlockSchema["table"], any, any>,
): {
/**
* The number of rows in the table.
Expand Down Expand Up @@ -370,7 +368,7 @@ export function getRelativeTableCells(
/**
* The table block containing the cell.
*/
block: BlockFromConfigNoChildren<DefaultBlockSchema["table"], any, any>,
block: BlockFromConfig<DefaultBlockSchema["table"], any, any>,
/**
* The occupancy grid of the table.
*/
Expand Down Expand Up @@ -428,7 +426,7 @@ export function getRelativeTableCells(
* @returns All of the cells associated with the relative row of the table. (All cells that have the same relative row index)
*/
export function getCellsAtRowHandle(
block: BlockFromConfigNoChildren<DefaultBlockSchema["table"], any, any>,
block: BlockFromConfig<DefaultBlockSchema["table"], any, any>,
relativeRowIndex: RelativeCellIndices["row"],
) {
const occupancyGrid = getTableCellOccupancyGrid(block);
Expand Down Expand Up @@ -507,7 +505,7 @@ export function getCellsAtRowHandle(
* @returns All of the cells associated with the relative column of the table. (All cells that have the same relative column index)
*/
export function getCellsAtColumnHandle(
block: BlockFromConfigNoChildren<DefaultBlockSchema["table"], any, any>,
block: BlockFromConfig<DefaultBlockSchema["table"], any, any>,
relativeColumnIndex: RelativeCellIndices["col"],
) {
const occupancyGrid = getTableCellOccupancyGrid(block);
Expand Down Expand Up @@ -563,7 +561,7 @@ export function getCellsAtColumnHandle(
* @note This is a destructive operation, it will modify the provided {@link OccupancyGrid} in place.
*/
export function moveColumn(
block: BlockFromConfigNoChildren<DefaultBlockSchema["table"], any, any>,
block: BlockFromConfig<DefaultBlockSchema["table"], any, any>,
fromColIndex: RelativeCellIndices["col"],
toColIndex: RelativeCellIndices["col"],
occupancyGrid: OccupancyGrid = getTableCellOccupancyGrid(block),
Expand Down Expand Up @@ -607,7 +605,7 @@ export function moveColumn(
* @note This is a destructive operation, it will modify the {@link OccupancyGrid} in place.
*/
export function moveRow(
block: BlockFromConfigNoChildren<DefaultBlockSchema["table"], any, any>,
block: BlockFromConfig<DefaultBlockSchema["table"], any, any>,
fromRowIndex: RelativeCellIndices["row"],
toRowIndex: RelativeCellIndices["row"],
occupancyGrid: OccupancyGrid = getTableCellOccupancyGrid(block),
Expand Down Expand Up @@ -682,7 +680,7 @@ function isCellEmpty(
* @note This is a destructive operation, it will modify the {@link OccupancyGrid} in place.
*/
export function cropEmptyRowsOrColumns(
block: BlockFromConfigNoChildren<DefaultBlockSchema["table"], any, any>,
block: BlockFromConfig<DefaultBlockSchema["table"], any, any>,
removeEmpty: "columns" | "rows",
occupancyGrid: OccupancyGrid = getTableCellOccupancyGrid(block),
): TableContent<any, any>["rows"] {
Expand Down Expand Up @@ -744,7 +742,7 @@ export function cropEmptyRowsOrColumns(
* @note This is a destructive operation, it will modify the {@link OccupancyGrid} in place.
*/
export function addRowsOrColumns(
block: BlockFromConfigNoChildren<DefaultBlockSchema["table"], any, any>,
block: BlockFromConfig<DefaultBlockSchema["table"], any, any>,
addType: "columns" | "rows",
/**
* The number of rows or columns to add.
Expand Down Expand Up @@ -800,7 +798,7 @@ export function addRowsOrColumns(
* Checks if a row can be safely dropped at the target row index without splitting merged cells.
*/
export function canRowBeDraggedInto(
block: BlockFromConfigNoChildren<DefaultBlockSchema["table"], any, any>,
block: BlockFromConfig<DefaultBlockSchema["table"], any, any>,
draggingIndex: RelativeCellIndices["row"],
targetRowIndex: RelativeCellIndices["row"],
) {
Expand Down Expand Up @@ -835,7 +833,7 @@ export function canRowBeDraggedInto(
* Checks if a column can be safely dropped at the target column index without splitting merged cells.
*/
export function canColumnBeDraggedInto(
block: BlockFromConfigNoChildren<DefaultBlockSchema["table"], any, any>,
block: BlockFromConfig<DefaultBlockSchema["table"], any, any>,
draggingIndex: RelativeCellIndices["col"],
targetColumnIndex: RelativeCellIndices["col"],
) {
Expand Down Expand Up @@ -874,7 +872,7 @@ export function canColumnBeDraggedInto(
export function areInSameColumn(
from: RelativeCellIndices,
to: RelativeCellIndices,
block: BlockFromConfigNoChildren<DefaultBlockSchema["table"], any, any>,
block: BlockFromConfig<DefaultBlockSchema["table"], any, any>,
) {
// Table indices are relative to the table, so we need to resolve the absolute cell indices
const anchorAbsoluteCellIndices = getAbsoluteTableCells(from, block);
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/api/exporters/html/externalHTMLExporter.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { DOMSerializer, Schema } from "prosemirror-model";

import { PartialBlock } from "../../../blocks/defaultBlocks.js";
import { Block } from "../../../blocks/defaultBlocks.js";
import type { BlockNoteEditor } from "../../../editor/BlockNoteEditor.js";
import {
BlockSchema,
Expand Down Expand Up @@ -40,7 +40,7 @@ export const createExternalHTMLExporter = <

return {
exportBlocks: (
blocks: PartialBlock<BSchema, I, S>[],
blocks: Block<BSchema, I, S>[],
options: { document?: Document },
) => {
const html = serializeBlocksExternalHTML(
Expand All @@ -62,7 +62,7 @@ export const createExternalHTMLExporter = <
) => {
const domFragment = serializeInlineContentExternalHTML(
editor,
inlineContent as any,
inlineContent as unknown as never,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

~~ as never? Why so? ~~
nvm, I see the todo

serializer,
options,
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { DOMSerializer, Schema } from "prosemirror-model";
import { PartialBlock } from "../../../blocks/defaultBlocks.js";

import { Block } from "../../../blocks/index.js";
import type { BlockNoteEditor } from "../../../editor/BlockNoteEditor.js";
import {
BlockSchema,
Expand Down Expand Up @@ -28,7 +29,7 @@ export const createInternalHTMLSerializer = <

return {
serializeBlocks: (
blocks: PartialBlock<BSchema, I, S>[],
blocks: Block<BSchema, I, S>[],
options: { document?: Document },
) => {
return serializeBlocksInternalHTML(editor, blocks, serializer, options)
Expand Down
Loading