diff --git a/docs/content/docs/features/custom-schemas/container-blocks.mdx b/docs/content/docs/features/custom-schemas/container-blocks.mdx index d9b56d1216..aa4bbc554c 100644 --- a/docs/content/docs/features/custom-schemas/container-blocks.mdx +++ b/docs/content/docs/features/custom-schemas/container-blocks.mdx @@ -11,7 +11,7 @@ You can create custom blocks that contain other blocks, such as panels, callouts ## Creating a Container Block -Use the `createReactBlockSpec` function to create a container block, just like a [Custom Block](/docs/features/custom-schemas/custom-blocks). For the panel below, we set `content` to `"none"` and add the `children` option to let it contain other blocks: +Use the `createReactBlockSpec` function to create a container block, just like a [Custom Block](/docs/features/custom-schemas/custom-blocks). For the panel below, we set `content` to `"none"` and `container` to `true`, so the panel's child blocks go inside it: ```tsx import { createReactBlockSpec } from "@blocknote/react"; @@ -21,7 +21,7 @@ export const createPanel = createReactBlockSpec( type: "panel", propSchema: {}, content: "none", - children: { allow: "blocks" }, + container: true, }, { render: (props) => ( @@ -35,15 +35,15 @@ export const createPanel = createReactBlockSpec( The block config defines the content and child blocks your container can hold: -`content:` Works the same as for [Custom Blocks](/docs/features/custom-schemas/custom-blocks#block-config-customblockconfig). When using the `children` option, choose `"none"`, `"inline"`, or `"plain"`. +`content:` Must be `"none"` for a container: its node holds nothing but its child blocks. For a block with its own text and child blocks, see [Combining Content and Child Blocks](#combining-content-and-child-blocks). -`children.allow:` Set to `"blocks"` to accept the editor's block types. You can also restrict a container to specific container types, as explained in [Restricting Children](#restricting-children). +`container:` Set to `true` to put the block's child blocks inside it. Without it, a block's child blocks are indented below it. A container accepts any block by default. You can also restrict it to specific container types, as explained in [Restricting Children](#restricting-children). `propSchema:` Defines the container's props, just like for other custom blocks. Use these to customize its appearance or behavior. ### Block Implementation -`render:` Your React component defines how the block should look. With `content: "none"`, attach `contentRef` where the child blocks should appear. With `content: "inline"` or `"plain"`, attach it to the block's own editable text. You can add icons, buttons, or other elements around it: +`render:` Your React component defines how the block should look. For a container, attach `contentRef` where the child blocks should appear. With `content: "inline"` or `"plain"`, attach it to the block's own editable text. You can add icons, buttons, or other elements around it: ```tsx render: (props) => ( @@ -109,7 +109,7 @@ A block can have both its own text and child blocks. Use this for a question fol -Set `content` to `"inline"` for rich text or `"plain"` for unstyled text, and add `children: { allow: "blocks" }`. Use `render` for the block's own text and `renderFrame` to style that content and its child blocks together: +Set `content` to `"inline"` for rich text or `"plain"` for unstyled text. Every block with content can have child blocks, so there's nothing to declare for them. Use `render` for the block's own text, `renderFrame` to style that content and its child blocks together, and `keyboard` to keep the child blocks inside the block: ```tsx import { createReactBlockSpec } from "@blocknote/react"; @@ -119,9 +119,13 @@ export const createCallout = createReactBlockSpec( type: "callout", propSchema: {}, content: "inline", - children: { allow: "blocks" }, }, { + keyboard: { + enter: "into-children", + childrenCanOutdent: false, + emptyChildEnter: "exit-at-end", + }, render: (props) => (
), @@ -146,9 +150,11 @@ The child blocks can still contain rich text, images, and other block types. `renderFrame:` An optional React component for styling the block and its children together, such as giving the callout a shared border or background. It receives `block`, `editor`, and `contentRef`, just like `render`. Attach `contentRef` where the block's content and children should appear. You can use the block's props to customize the frame, add interactive controls, or return `null` to show the block without a frame. -You can also use `renderFrame` without the `children` option to style a block and its indented children together. For a container with `content: "none"`, like the panel above, add the surrounding styling directly in `render`. +`keyboard:` Without it, child blocks behave like any indented blocks. Here, `enter: "into-children"` makes Enter in the title add a first child block, `childrenCanOutdent: false` keeps Shift-Tab from moving blocks out of the callout, and `emptyChildEnter: "exit-at-end"` makes Enter in an empty last block leave the callout. See [Custom Blocks](/docs/features/custom-schemas/custom-blocks) for all keyboard settings. + +For a container with `content: "none"`, like the panel above, add the surrounding styling directly in `render`. -Add `callout: createCallout()` to your schema, then use `content` for the title and `children` for the body: +Add `callout: createCallout()` to your schema, then use `content` for the title and `children` for the blocks inside it: ```typescript { @@ -160,7 +166,7 @@ Add `callout: createCallout()` to your schema, then use `content` for the title } ``` -Pressing Enter at the end of the title starts a paragraph in the body. Moving the callout moves its title and body together. +Pressing Enter at the end of the title adds a paragraph inside the callout, and Enter in an empty last paragraph leaves the callout. Moving the callout moves its title and child blocks together. To add blocks to an existing container, see [Inserting Blocks](/docs/reference/editor/manipulating-content#inserting-blocks). @@ -172,6 +178,7 @@ Use an array of container type names for `children.allow`, and `min` to set the ```typescript // Column layout config: +container: true, children: { allow: ["column"], min: 2 }, ``` @@ -179,16 +186,16 @@ On the column itself, set `placeable` to `"namedOnly"` so it can only be used in ```typescript // Column config: -children: { allow: "blocks" }, +container: true, placeable: "namedOnly", ``` -`children.allow:` Accepts `"blocks"` or an array of container type names. You cannot list regular block types such as `"paragraph"` individually. +`children.allow:` Accepts `"blocks"` (the default) or an array of container type names. You cannot list regular block types such as `"paragraph"` individually. `children.min:` The minimum number of children. Defaults to `1`. `placeable:` Set to `"namedOnly"` to restrict a container to parents that name it in `children.allow`. Defaults to `"anywhere"`. -These options apply to containers with `content: "none"`. Blocks with `content: "inline"` or `"plain"` use `children: { allow: "blocks" }` and can have no child blocks. +These options need `container: true`. Other blocks can always have child blocks of any type, so for them `children` can only be the default, `{ allow: "blocks" }`. For built-in column blocks, see [Multi-Column Layouts](/docs/foundations/document-structure#column-blocks). diff --git a/docs/content/docs/features/custom-schemas/custom-blocks.mdx b/docs/content/docs/features/custom-schemas/custom-blocks.mdx index 4146907f28..d446aa8afe 100644 --- a/docs/content/docs/features/custom-schemas/custom-blocks.mdx +++ b/docs/content/docs/features/custom-schemas/custom-blocks.mdx @@ -56,8 +56,9 @@ type BlockConfig = { type: string; content: "inline" | "plain" | "none"; readonly propSchema: PropSchema; + container?: true; // only with content: "none" children?: { - allow: "blocks" | string[]; + allow?: "blocks" | string[]; min?: number; }; placeable?: "anywhere" | "namedOnly"; @@ -78,12 +79,12 @@ type BlockConfig = { - _Custom blocks can also contain child blocks by declaring the `children` - option, with or without editable content of their own. See [Container - Blocks](/docs/features/custom-schemas/container-blocks)._ + _Every block can have child blocks, indented below it. A block without + content can also hold them inside itself with `container: true`. See + [Container Blocks](/docs/features/custom-schemas/container-blocks)._ -`children?:` Defines which child blocks the block can contain. `placeable?:` Controls where a container block can be used. See [Container Blocks](/docs/features/custom-schemas/container-blocks) for the supported configurations. +`container?:` Puts the block's child blocks inside it. `children?:` Restricts which child blocks a container can hold. `placeable?:` Controls where a container block can be used. See [Container Blocks](/docs/features/custom-schemas/container-blocks) for the supported configurations. `propSchema:` The `PropSchema` specifies the props that the block supports. Block props (properties) are data stored with your Block in the document, and can be used to customize its appearance or behavior. @@ -146,8 +147,17 @@ type ReactCustomBlockImplementation = { schema: Schema; }) => Fragment | undefined; runsBefore?: string[]; + keyboard?: KeyboardSettings | ((block: Block) => KeyboardSettings); + // KeyboardSettings: { + // enter?: "split" | "into-children" | "line-break"; + // shiftEnter?: "line-break" | "same-as-enter"; + // splitKeepsType?: boolean; + // resetsTo?: { type: string; props?: Record }; + // emptyEnterResets?: boolean; + // emptyChildEnter?: "outdent" | "exit-at-end" | "stay"; + // childrenCanOutdent?: boolean; + // } meta?: { - hardBreakShortcut?: "shift+enter" | "enter" | "none"; selectable?: boolean; fileBlockAccept?: string[]; code?: boolean; @@ -184,9 +194,25 @@ type ReactCustomBlockImplementation = { `runsBefore?:` If this block has parsing or extensions that need to be given priority over any other blocks, you can pass their `type`s in an array here. -`meta?:` An object for setting various generic properties of the block. +`keyboard?:` How the keyboard treats the block and its children. Give only the settings that differ from the defaults. To make settings depend on the block's props, give a function that gets the block and returns them instead. + +- `enter?:` What Enter does in the block's content. `"split"` (default) splits the block, moving the text after the caret into a new block below. `"into-children"` moves it into a new first child instead. `"line-break"` inserts a line break, and makes Shift-Enter do the same. For `content: "plain"` blocks (which can't hold hard break nodes), a line break is a literal newline (`"\n"`). + +- `shiftEnter?:` What Shift-Enter does in the block's content: `"line-break"` (default) or `"same-as-enter"`. + +- `splitKeepsType?:` Whether the block created by splitting this one with Enter has the same type, as in lists. Defaults to `false`. + +- `resetsTo?:` What the block turns into when it's reset, keeping its content and children. Backspace at the start of the block always resets it. A `type`, and `props` to merge into the block's props. Defaults to `{ type: "paragraph" }`. -- `hardBreakShortcut?:` Defines which keyboard shortcut should be used to insert a hard break into the block's inline content. Defaults to `"shift+enter"`. For `content: "plain"` blocks (which can't hold hard break nodes), the shortcut inserts a literal newline (`"\n"`) instead. +- `emptyEnterResets?:` Whether Enter in the empty block resets it too, as when an empty list item turns into a paragraph. Defaults to `false`. + +- `emptyChildEnter?:` What Enter does in an empty child of this block. `"outdent"` (default) outdents any empty child. `"exit-at-end"` (default for container blocks) moves an empty last child out to after the block, and adds a new child after any other empty child. `"stay"` always adds a new child after it. + +- `childrenCanOutdent?:` Whether the block's children can be outdented out of it with Shift-Tab, or by Enter or Backspace in an empty or nested child. Defaults to `true`, or `false` for container blocks, whose children can never be outdented. + +When settings meet, Enter at the start of non-empty content always inserts an empty block above it, and resetting an empty block comes before `enter: "into-children"`. + +`meta?:` An object for setting various generic properties of the block. - `selectable?:` Can be set to false in order to make the block non-selectable, both using the mouse and keyboard. This also helps with being able to select non-editable content within the block. Should only be set to false when `content` is `none` and defaults to true. diff --git a/docs/content/docs/features/custom-schemas/source-with-preview.mdx b/docs/content/docs/features/custom-schemas/source-with-preview.mdx index 03dd18c51e..343168c87d 100644 --- a/docs/content/docs/features/custom-schemas/source-with-preview.mdx +++ b/docs/content/docs/features/custom-schemas/source-with-preview.mdx @@ -62,7 +62,7 @@ return ( A few more props customize the states: `errorPreview` for the compact error state shown in place of the preview, `emptySourcePlaceholder` for when the source is empty (a string customizes the default placeholder's text, an element — e.g. the exported `PreviewPlaceholder` with your own icon — replaces it entirely), and `sourcePlaceholder` for the popup input's placeholder. See the `SourceWithPreviewProps` type for the full list. -**3. The spec's `meta`**, opting into the popup: +**3. The spec's `meta`**, opting into the popup, and its `keyboard`: ```tsx const createMyBlockSpec = createReactBlockSpec(createMyBlockConfig, { @@ -70,10 +70,12 @@ const createMyBlockSpec = createReactBlockSpec(createMyBlockConfig, { code: true, // Marks the block as rendering a preview with an editable source popup. hasPreview: true, - // What Enter does while the popup is open: "enter" inserts a newline - // (multiline sources, like diagrams), "shift+enter" closes the popup - // (single-line sources, like math). - hardBreakShortcut: "enter", + }, + // What Enter does while the popup is open: "line-break" inserts a newline + // (multiline sources, like diagrams). Without it, Enter closes the popup + // (single-line sources, like math). + keyboard: { + enter: "line-break", }, render: MyBlockPreview, }); diff --git a/docs/content/docs/features/export/typst.mdx b/docs/content/docs/features/export/typst.mdx index 39e908cba7..0485b0839b 100644 --- a/docs/content/docs/features/export/typst.mdx +++ b/docs/content/docs/features/export/typst.mdx @@ -120,18 +120,22 @@ For a block with inline content, render it the way the default mappings do: `exporter.transformInlineContent(block.content).join("")` (inline results are markup strings, so plain concatenation composes them). -### Container blocks +### Blocks that place their children -A [container block](/docs/features/custom-schemas/container-blocks) holds -child blocks, and its mapping decides where they go: the exporter renders the -children first and passes them in as the mapping's last argument, rather than -appending them after the container's own output. A container without a -mapping is an error rather than a silent omission, since dropping it would -drop its children too. +By default, a mapping renders only its block, and the exporter places the +block's children after it, indented. A block whose children are part of it - +a [container block](/docs/features/custom-schemas/container-blocks), or a +callout with a body - uses a `{ withChildren }` mapping instead: the exporter renders +the children first and passes them in as its last argument, and the mapping +decides where they go. Container blocks must use a `{ withChildren }` mapping, and a +container without one is an error rather than a silent omission, since +dropping it would drop its children too. ```typescript -myContainer: (block, exporter, nestingLevel, numberedListIndex, children) => - `#rect(width: 100%)[${children.join("\n\n")}]`, +myContainer: { + withChildren: (block, exporter, nestingLevel, numberedListIndex, children) => + `#rect(width: 100%)[${children.join("\n\n")}]`, +}, ``` Separate the children with a blank line, as above, if each should stay its own diff --git a/examples/06-custom-schema/06-toggleable-blocks/.bnexample.json b/examples/06-custom-schema/06-toggleable-blocks/.bnexample.json deleted file mode 100644 index 6d4a02dd52..0000000000 --- a/examples/06-custom-schema/06-toggleable-blocks/.bnexample.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "playground": true, - "docs": true, - "author": "matthewlipski", - "tags": ["Basic"] -} diff --git a/examples/06-custom-schema/06-toggleable-blocks/README.md b/examples/06-custom-schema/06-toggleable-blocks/README.md deleted file mode 100644 index 4bbaaa70e1..0000000000 --- a/examples/06-custom-schema/06-toggleable-blocks/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# Toggleable Custom Blocks - -This example shows how to create custom blocks with a toggle button to show/hide their children, like with the default toggle heading and list item blocks. This is done using the use the `ToggleWrapper` component from `@blocknote/react`. - -**Relevant Docs:** - -- [Custom Blocks](/docs/features/custom-schemas/custom-blocks) -- [Editor Setup](/docs/getting-started/editor-setup) -- [Default Schema](/docs/features/blocks) diff --git a/examples/06-custom-schema/06-toggleable-blocks/index.html b/examples/06-custom-schema/06-toggleable-blocks/index.html deleted file mode 100644 index bdac14de54..0000000000 --- a/examples/06-custom-schema/06-toggleable-blocks/index.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - Toggleable Custom Blocks - - - -
- - - diff --git a/examples/06-custom-schema/06-toggleable-blocks/main.tsx b/examples/06-custom-schema/06-toggleable-blocks/main.tsx deleted file mode 100644 index 1260513388..0000000000 --- a/examples/06-custom-schema/06-toggleable-blocks/main.tsx +++ /dev/null @@ -1,11 +0,0 @@ -// AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY -import React from "react"; -import { createRoot } from "react-dom/client"; -import App from "./src/App.jsx"; - -const root = createRoot(document.getElementById("root")!); -root.render( - - - , -); diff --git a/examples/06-custom-schema/06-toggleable-blocks/package.json b/examples/06-custom-schema/06-toggleable-blocks/package.json deleted file mode 100644 index caed51c711..0000000000 --- a/examples/06-custom-schema/06-toggleable-blocks/package.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "@blocknote/example-custom-schema-toggleable-blocks", - "description": "AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY", - "type": "module", - "private": true, - "version": "0.12.4", - "scripts": { - "start": "vite", - "dev": "vite", - "build:prod": "tsc && vite build", - "preview": "vite preview" - }, - "dependencies": { - "@blocknote/ariakit": "latest", - "@blocknote/core": "latest", - "@blocknote/mantine": "latest", - "@blocknote/react": "latest", - "@blocknote/shadcn": "latest", - "@mantine/core": "^9.0.2", - "@mantine/hooks": "^9.0.2", - "react": "^19.2.3", - "react-dom": "^19.2.3" - }, - "devDependencies": { - "@types/react": "^19.2.3", - "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^6.0.1", - "vite": "^8.0.0" - } -} diff --git a/examples/06-custom-schema/06-toggleable-blocks/src/App.tsx b/examples/06-custom-schema/06-toggleable-blocks/src/App.tsx deleted file mode 100644 index 81877de7e4..0000000000 --- a/examples/06-custom-schema/06-toggleable-blocks/src/App.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { BlockNoteSchema, defaultBlockSpecs } from "@blocknote/core"; -import "@blocknote/core/fonts/inter.css"; -import { BlockNoteView } from "@blocknote/mantine"; -import "@blocknote/mantine/style.css"; -import { useCreateBlockNote } from "@blocknote/react"; - -import { ToggleBlock } from "./Toggle"; - -// Our schema with block specs, which contain the configs and implementations for -// blocks that we want our editor to use. -const schema = BlockNoteSchema.create({ - blockSpecs: { - // Adds all default blocks. - ...defaultBlockSpecs, - // Adds the Toggle block. - toggle: ToggleBlock(), - }, -}); - -export default function App() { - // Creates a new editor instance. - const editor = useCreateBlockNote({ - schema, - initialContent: [ - { - type: "paragraph", - content: "Welcome to this demo!", - }, - { - // We set a persistent ID so that the toggled state is preserved - // on reload. - id: "toggle", - type: "toggle", - content: "This is an example toggle", - children: [ - { - type: "paragraph", - content: "This is the first child of the toggle block.", - }, - { - type: "paragraph", - content: "This is the second child of the toggle block.", - }, - ], - }, - { - type: "paragraph", - content: "Click the '>' icon to show/hide its children", - }, - ], - }); - - // Renders the editor instance. - return ; -} diff --git a/examples/06-custom-schema/06-toggleable-blocks/src/Toggle.tsx b/examples/06-custom-schema/06-toggleable-blocks/src/Toggle.tsx deleted file mode 100644 index 244661f841..0000000000 --- a/examples/06-custom-schema/06-toggleable-blocks/src/Toggle.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { defaultProps } from "@blocknote/core"; -import { createReactBlockSpec, ToggleWrapper } from "@blocknote/react"; - -// The Toggle block that we want to add to our editor. -export const ToggleBlock = createReactBlockSpec( - { - type: "toggle", - propSchema: { - ...defaultProps, - }, - content: "inline", - }, - { - render: (props) => ( - // The `ToggleWrapper` component renders a button on the left which - // toggles the visibility of the block's children. It also adds a button - // to add child blocks if there are none. By default, it uses local - // storage to remember the toggled state based on the block ID, but you can pass a custom - // `toggledState` prop to use a different storage mechanism. - -

- - ), - }, -); diff --git a/examples/06-custom-schema/06-toggleable-blocks/src/vite-env.d.ts b/examples/06-custom-schema/06-toggleable-blocks/src/vite-env.d.ts deleted file mode 100644 index bc2d8a36f3..0000000000 --- a/examples/06-custom-schema/06-toggleable-blocks/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/examples/06-custom-schema/06-toggleable-blocks/tsconfig.json b/examples/06-custom-schema/06-toggleable-blocks/tsconfig.json deleted file mode 100644 index 2aa62c56e6..0000000000 --- a/examples/06-custom-schema/06-toggleable-blocks/tsconfig.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "__comment": "AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY", - "compilerOptions": { - "target": "ESNext", - "useDefineForClassFields": true, - "lib": ["DOM", "DOM.Iterable", "ESNext"], - "allowJs": false, - "skipLibCheck": true, - "allowSyntheticDefaultImports": true, - "strict": true, - "forceConsistentCasingInFileNames": true, - "module": "ESNext", - "moduleResolution": "bundler", - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "react-jsx", - "composite": true, - "paths": { - "@shared/*": ["../../../shared/*"] - } - }, - "include": ["."], - "__ADD_FOR_LOCAL_DEV_references": [ - { - "path": "../../../packages/core/" - }, - { - "path": "../../../packages/react/" - } - ] -} diff --git a/examples/06-custom-schema/06-toggleable-blocks/vite-env.d.ts b/examples/06-custom-schema/06-toggleable-blocks/vite-env.d.ts deleted file mode 100644 index 11f02fe2a0..0000000000 --- a/examples/06-custom-schema/06-toggleable-blocks/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/examples/06-custom-schema/06-toggleable-blocks/vite.config.ts b/examples/06-custom-schema/06-toggleable-blocks/vite.config.ts deleted file mode 100644 index cbf6ff2ffc..0000000000 --- a/examples/06-custom-schema/06-toggleable-blocks/vite.config.ts +++ /dev/null @@ -1,35 +0,0 @@ -// AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY -import react from "@vitejs/plugin-react"; -import * as fs from "fs"; -import * as path from "path"; -import { defineConfig } from "vite"; -// https://vitejs.dev/config/ -export default defineConfig(((conf: { command: string }) => ({ - plugins: [react()], - optimizeDeps: {}, - build: { - sourcemap: true, - }, - resolve: { - alias: - conf.command === "build" || - !fs.existsSync(path.resolve(__dirname, "../../../packages/core/src")) - ? {} - : ({ - // The repo-wide alias for the shared test-utils directory (private, - // so it only resolves inside the monorepo). Harmless for examples - // that don't use it. - "@shared": path.resolve(__dirname, "../../../shared/"), - // Comment out the lines below to load a built version of blocknote - // or, keep as is to load live from sources with live reload working - "@blocknote/core": path.resolve( - __dirname, - "../../../packages/core/src/", - ), - "@blocknote/react": path.resolve( - __dirname, - "../../../packages/react/src/", - ), - } as any), - }, -})) as Parameters[0]); diff --git a/examples/06-custom-schema/09-container-block/README.md b/examples/06-custom-schema/09-container-block/README.md index 999bf62786..5ecd226989 100644 --- a/examples/06-custom-schema/09-container-block/README.md +++ b/examples/06-custom-schema/09-container-block/README.md @@ -2,7 +2,7 @@ In this example, we create a custom `Panel` block that holds other blocks as its body, such as a panel containing headings and paragraphs. -The block declares the `children` config on `BlockConfig`. `children: { allow: "blocks" }` makes it a container: its child blocks mount into the rendered content region (attached with `ref={contentRef}`), and live on `block.children` at runtime. A pure container like this draws its box in `render`, which re-renders live when props change. +The block sets `container: true` on `BlockConfig`, which makes it a container: its child blocks mount into the rendered content region (attached with `ref={contentRef}`), and live on `block.children` at runtime. A pure container like this draws its box in `render`, which re-renders live when props change. We also wire up a Slash Menu item to insert the panel. diff --git a/examples/06-custom-schema/09-container-block/index.html b/examples/06-custom-schema/09-container-block/index.html index 19321f77b5..34d12680d0 100644 --- a/examples/06-custom-schema/09-container-block/index.html +++ b/examples/06-custom-schema/09-container-block/index.html @@ -1,7 +1,10 @@ - + Container Block