Skip to content

Support h4, h5, and h6 #1634

New issue

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

By clicking “No 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? No Sign in to your account

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
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
102 changes: 30 additions & 72 deletions packages/core/src/blocks/HeadingBlockContent/HeadingBlockContent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import {
import { createDefaultBlockDOMOutputSpec } from "../defaultBlockHelpers.js";
import { defaultProps } from "../defaultProps.js";

const HEADING_LEVELS = [1, 2, 3, 4, 5, 6] as const;

export const headingPropSchema = {
...defaultProps,
level: { default: 1, values: [1, 2, 3] as const },
level: { default: 1, values: HEADING_LEVELS },
} satisfies PropSchema;

const HeadingBlockContent = createStronglyTypedTiptapNode({
Expand All @@ -26,7 +28,7 @@ const HeadingBlockContent = createStronglyTypedTiptapNode({

addInputRules() {
return [
...[1, 2, 3].map((level) => {
...HEADING_LEVELS.map((level) => {
// Creates a heading of appropriate level when starting with "#", "##", or "###".
return new InputRule({
find: new RegExp(`^(#{${level}})\\s$`),
Expand Down Expand Up @@ -58,84 +60,40 @@ const HeadingBlockContent = createStronglyTypedTiptapNode({
},

addKeyboardShortcuts() {
return {
"Mod-Alt-1": () => {
const blockInfo = getBlockInfoFromSelection(this.editor.state);
if (
!blockInfo.isBlockContainer ||
blockInfo.blockContent.node.type.spec.content !== "inline*"
) {
return true;
}

// call updateBlockCommand
return this.editor.commands.command(
updateBlockCommand(blockInfo.bnBlock.beforePos, {
type: "heading",
props: {
level: 1 as any,
},
})
);
},
"Mod-Alt-2": () => {
const blockInfo = getBlockInfoFromSelection(this.editor.state);
if (
!blockInfo.isBlockContainer ||
blockInfo.blockContent.node.type.spec.content !== "inline*"
) {
return true;
}

return this.editor.commands.command(
updateBlockCommand(blockInfo.bnBlock.beforePos, {
type: "heading",
props: {
level: 2 as any,
},
})
);
},
"Mod-Alt-3": () => {
const blockInfo = getBlockInfoFromSelection(this.editor.state);
if (
!blockInfo.isBlockContainer ||
blockInfo.blockContent.node.type.spec.content !== "inline*"
) {
return true;
}
return Object.fromEntries(
HEADING_LEVELS.map((level) => [
`Mod-Alt-${level}`,
() => {
const blockInfo = getBlockInfoFromSelection(this.editor.state);
if (
!blockInfo.isBlockContainer ||
blockInfo.blockContent.node.type.spec.content !== "inline*"
) {
return true;
}

return this.editor.commands.command(
updateBlockCommand(blockInfo.bnBlock.beforePos, {
type: "heading",
props: {
level: 3 as any,
},
})
);
},
};
return this.editor.commands.command(
updateBlockCommand(blockInfo.bnBlock.beforePos, {
type: "heading",
props: {
level: level as any,
},
})
);
},
])
);
},
parseHTML() {
return [
{
tag: "div[data-content-type=" + this.name + "]",
},
{
tag: "h1",
attrs: { level: 1 },
...HEADING_LEVELS.map((level) => ({
tag: `h${level}`,
attrs: { level },
node: "heading",
},
{
tag: "h2",
attrs: { level: 2 },
node: "heading",
},
{
tag: "h3",
attrs: { level: 3 },
node: "heading",
},
})),
];
},

Expand Down
18 changes: 18 additions & 0 deletions packages/core/src/editor/Block.css
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,15 @@ NESTED BLOCKS
[data-content-type="heading"][data-level="3"] {
--level: 1.3em;
}
[data-content-type="heading"][data-level="4"] {
--level: 1em;
}
[data-content-type="heading"][data-level="5"] {
--level: 0.9em;
}
[data-content-type="heading"][data-level="6"] {
--level: 0.8em;
}

[data-prev-level="1"] {
--prev-level: 3em;
Expand All @@ -136,6 +145,15 @@ NESTED BLOCKS
[data-prev-level="3"] {
--prev-level: 1.3em;
}
[data-prev-level="4"] {
--prev-level: 1em;
}
[data-prev-level="5"] {
--prev-level: 0.9em;
}
[data-prev-level="6"] {
--prev-level: 0.8em;
}

.bn-block-outer[data-prev-type="heading"] > .bn-block > .bn-block-content {
font-size: var(--prev-level);
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/editor/editor.css
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ Tippy popups that are appended to document.body directly
.bn-default-styles h1,
.bn-default-styles h2,
.bn-default-styles h3,
.bn-default-styles h4,
.bn-default-styles h5,
.bn-default-styles h6,
.bn-default-styles li {
margin: 0;
padding: 0;
Expand Down
18 changes: 18 additions & 0 deletions packages/core/src/i18n/locales/ar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,24 @@ export const ar: Dictionary = {
aliases: ["ع3", "عنوان3", "عنوان فرعي"],
group: "العناوين",
},
heading_4: {
title: "عنوان 4",
subtext: "عنوان فرعي ثانوي صغير",
aliases: ["ع4", "عنوان4", "عنوان فرعي صغير"],
group: "العناوين",
},
heading_5: {
title: "عنوان 5",
subtext: "عنوان فرعي صغير",
aliases: ["ع5", "عنوان5", "عنوان فرعي صغير"],
group: "العناوين",
},
heading_6: {
title: "عنوان 6",
subtext: "أدنى مستوى للعناوين",
aliases: ["ع6", "عنوان6", "العنوان الفرعي الأدنى"],
group: "العناوين",
},
quote: {
title: "اقتباس",
subtext: "اقتباس أو مقتطف",
Expand Down
18 changes: 18 additions & 0 deletions packages/core/src/i18n/locales/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,24 @@ export const de: Dictionary = {
aliases: ["h3", "überschrift3", "unterüberschrift"],
group: "Überschriften",
},
heading_4: {
title: "Überschrift 4",
subtext: "Überschrift für kleinere Unterabschnitte",
aliases: ["h4", "überschrift4", "unterüberschrift4"],
group: "Überschriften",
},
heading_5: {
title: "Überschrift 5",
subtext: "Überschrift für tiefere Unterabschnitte",
aliases: ["h5", "überschrift5", "unterüberschrift5"],
group: "Überschriften",
},
heading_6: {
title: "Überschrift 6",
subtext: "Überschrift auf der untersten Ebene",
aliases: ["h6", "überschrift6", "unterüberschrift6"],
group: "Überschriften",
},
quote: {
title: "Zitat",
subtext: "Zitat oder Auszug",
Expand Down
18 changes: 18 additions & 0 deletions packages/core/src/i18n/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,24 @@ export const en = {
aliases: ["h3", "heading3", "subheading"],
group: "Headings",
},
heading_4: {
title: "Heading 4",
subtext: "Minor subsection heading",
aliases: ["h4", "heading4", "subheading4"],
group: "Headings",
},
heading_5: {
title: "Heading 5",
subtext: "Small subsection heading",
aliases: ["h5", "heading5", "subheading5"],
group: "Headings",
},
heading_6: {
title: "Heading 6",
subtext: "Lowest-level heading",
aliases: ["h6", "heading6", "subheading6"],
group: "Headings",
},
quote: {
title: "Quote",
subtext: "Quote or excerpt",
Expand Down
18 changes: 18 additions & 0 deletions packages/core/src/i18n/locales/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,24 @@ export const es: Dictionary = {
aliases: ["h3", "encabezado3", "subencabezado"],
group: "Encabezados",
},
heading_4: {
title: "Encabezado 4",
subtext: "Encabezado de subsección menor",
aliases: ["h4", "encabezado4", "subencabezado4"],
group: "Encabezados",
},
heading_5: {
title: "Encabezado 5",
subtext: "Encabezado de subsección pequeña",
aliases: ["h5", "encabezado5", "subencabezado5"],
group: "Encabezados",
},
heading_6: {
title: "Encabezado 6",
subtext: "Encabezado de nivel más bajo",
aliases: ["h6", "encabezado6", "subencabezado6"],
group: "Encabezados",
},
quote: {
title: "Cita",
subtext: "Cita o extracto",
Expand Down
18 changes: 18 additions & 0 deletions packages/core/src/i18n/locales/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,24 @@ export const fr: Dictionary = {
aliases: ["h3", "titre3", "sous-titre"],
group: "Titres",
},
heading_4: {
title: "Titre 4",
subtext: "Titre de sous‑section mineure",
aliases: ["h4", "titre4", "sous‑titre4"],
group: "Titres",
},
heading_5: {
title: "Titre 5",
subtext: "Titre de sous-section mineure",
aliases: ["h5", "titre5", "sous-titre5"],
group: "Titres",
},
heading_6: {
title: "Titre 6",
subtext: "Titre de niveau le plus bas",
aliases: ["h6", "titre6", "sous-titre6"],
group: "Titres",
},
quote: {
title: "Citation",
subtext: "Citation ou extrait",
Expand Down
18 changes: 18 additions & 0 deletions packages/core/src/i18n/locales/hr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,24 @@ export const hr: Dictionary = {
aliases: ["h3", "naslov3", "podnaslov"],
group: "Naslovi",
},
heading_4: {
title: "Naslov 4",
subtext: "Manji naslov podpoglavlja",
aliases: ["h4", "naslov4", "podnaslov4"],
group: "Naslovi",
},
heading_5: {
title: "Naslov 5",
subtext: "Mali naslov podpoglavlja",
aliases: ["h5", "naslov5", "podnaslov5"],
group: "Naslovi",
},
heading_6: {
title: "Naslov 6",
subtext: "Naslov najniže razine",
aliases: ["h6", "naslov6", "podnaslov6"],
group: "Naslovi",
},
quote: {
title: "Citat",
subtext: "Citat ili izvadak",
Expand Down
18 changes: 18 additions & 0 deletions packages/core/src/i18n/locales/is.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,24 @@ export const is: Dictionary = {
aliases: ["h3", "fyrirsogn3", "undirfyrirsogn"],
group: "Fyrirsagnir",
},
heading_4: {
title: "Fyrirsögn 4",
subtext: "Titill fyrir minni undirhluta",
aliases: ["h4", "fyrirsogn4", "undirfyrirsogn4"],
group: "Fyrirsagnir",
},
heading_5: {
title: "Fyrirsögn 5",
subtext: "Titill fyrir litla undirkafla",
aliases: ["h5", "fyrirsogn5", "undirfyrirsogn5"],
group: "Fyrirsagnir",
},
heading_6: {
title: "Fyrirsögn 6",
subtext: "Titill á lægsta stigi",
aliases: ["h6", "fyrirsogn6", "undirfyrirsogn6"],
group: "Fyrirsagnir",
},
quote: {
title: "Tilvitnun",
subtext: "Tilvitnun eða útdráttur",
Expand Down
18 changes: 18 additions & 0 deletions packages/core/src/i18n/locales/it.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,24 @@ export const it: Dictionary = {
aliases: ["h3", "intestazione3", "sottotitolo"],
group: "Intestazioni",
},
heading_4: {
title: "Intestazione 4",
subtext: "Intestazione di sottosezione minore",
aliases: ["h4", "intestazione4", "sottotitolo4"],
group: "Intestazioni",
},
heading_5: {
title: "Intestazione 5",
subtext: "Intestazione di sottosezione minore",
aliases: ["h5", "intestazione5", "sottotitolo5"],
group: "Intestazioni",
},
heading_6: {
title: "Intestazione 6",
subtext: "Intestazione di livello più basso",
aliases: ["h6", "intestazione6", "sottotitolo6"],
group: "Intestazioni",
},
quote: {
title: "Citazione",
subtext: "Citazione o estratto",
Expand Down
18 changes: 18 additions & 0 deletions packages/core/src/i18n/locales/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,24 @@ export const ja: Dictionary = {
aliases: ["h3", "見出し3", "subheading", "小見出し"],
group: "見出し",
},
heading_4: {
title: "見出し4",
subtext: "小さなサブセクションの見出しに使用",
aliases: ["h4", "見出し4", "subheading4", "小見出し4"],
group: "見出し",
},
heading_5: {
title: "見出し5",
subtext: "小さなサブセクションの見出しに使用",
aliases: ["h5", "見出し5", "subheading5", "小見出し5"],
group: "見出し",
},
heading_6: {
title: "見出し6",
subtext: "最下位レベルの見出しに使用",
aliases: ["h6", "見出し6", "subheading6", "小見出し6"],
group: "見出し",
},
quote: {
title: "引用",
subtext: "引用または抜粋",
Expand Down
Loading