feat: add buttons for superscript and subscript

This commit is contained in:
Steffen Becker committed 2026-06-10 02:19:03 +02:00
1 parent b28a33b104
commit 872414ef23
5 files changed
+78

No files matched your search

+30
View File
@@ -23,6 +23,8 @@
"@tiptap/extension-paragraph": "^3.23.6",
"@tiptap/extension-placeholder": "^3.23.6",
"@tiptap/extension-strike": "^3.23.6",
"@tiptap/extension-subscript": "^3.23.6",
"@tiptap/extension-superscript": "^3.23.6",
"@tiptap/extension-table": "3.23.6",
"@tiptap/extension-text": "^3.23.6",
"@tiptap/extension-text-align": "^3.23.6",
@@ -643,6 +645,34 @@
"@tiptap/core": "3.23.6"
}
},
"node_modules/@tiptap/extension-subscript": {
"version": "3.23.6",
"resolved": "https://registry.npmjs.org/@tiptap/extension-subscript/-/extension-subscript-3.23.6.tgz",
"integrity": "sha512-K9NP2sAjoQ0EKnPVw96864aMXZlK5r3cTaybg7vQ6kKIM9OEOB+36F4VHQgQdpYUMk94gxSP/ixBB8bTVN8lPA==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "3.23.6",
"@tiptap/pm": "3.23.6"
}
},
"node_modules/@tiptap/extension-superscript": {
"version": "3.23.6",
"resolved": "https://registry.npmjs.org/@tiptap/extension-superscript/-/extension-superscript-3.23.6.tgz",
"integrity": "sha512-GTVHfik32a6m4q8rU3nl0mUKUfz3kTd+qIxUCGvoS/1Adb9M5Q0i5bfLk5jDOW896iCn00hPW7GbkP7WRd2Mhg==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "3.23.6",
"@tiptap/pm": "3.23.6"
}
},
"node_modules/@tiptap/extension-table": {
"version": "3.23.6",
"resolved": "https://registry.npmjs.org/@tiptap/extension-table/-/extension-table-3.23.6.tgz",
+2
View File
@@ -37,6 +37,8 @@
"@tiptap/extension-paragraph": "^3.23.6",
"@tiptap/extension-placeholder": "^3.23.6",
"@tiptap/extension-strike": "^3.23.6",
"@tiptap/extension-subscript": "^3.23.6",
"@tiptap/extension-superscript": "^3.23.6",
"@tiptap/extension-table": "3.23.6",
"@tiptap/extension-text": "^3.23.6",
"@tiptap/extension-text-align": "^3.23.6",
+40
View File
@@ -270,6 +270,19 @@
let currentFontColor = $derived(uniformMarkColor('textStyle'));
let currentHighlightColor = $derived(uniformMarkColor('highlight'));
// Sub/superscript are mutually exclusive (Word-style): toggling one clears the
// other. odf-kit maps these marks to text:position (round-trips with LibreOffice
// and Word). See export/odt.ts applyRuns for the custom-attr-paragraph path.
let isSuperscript = $derived(tick >= 0 && !!editor?.isActive('superscript'));
let isSubscript = $derived(tick >= 0 && !!editor?.isActive('subscript'));
function toggleSuperscript() {
editor?.chain().focus().unsetSubscript().toggleSuperscript().run();
}
function toggleSubscript() {
editor?.chain().focus().unsetSuperscript().toggleSubscript().run();
}
let fontOpen = $state(false);
let sizeOpen = $state(false);
let lineHeightOpen = $state(false);
@@ -777,6 +790,33 @@
<div class="toolbar-separator"></div>
<div class="toolbar-group">
<button
class:active={isSuperscript}
onclick={toggleSuperscript}
title="Superscript (Ctrl+.)"
aria-pressed={isSuperscript}
>
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
<path d="M2.5 11.5L7 5M7 11.5L2.5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M10.5 4.7c0-.8.7-1.4 1.5-1.4s1.5.6 1.5 1.4c0 1.2-1.6 1.5-3 3.1h3" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
<button
class:active={isSubscript}
onclick={toggleSubscript}
title="Subscript (Ctrl+,)"
aria-pressed={isSubscript}
>
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
<path d="M2.5 11.5L7 5M7 11.5L2.5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M10.5 12.2c0-.8.7-1.4 1.5-1.4s1.5.6 1.5 1.4c0 1.2-1.6 1.5-3 3.1h3" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
</div>
<div class="toolbar-separator"></div>
<div class="lh-picker" use:lineHeightPickerClickOutside>
<button class="lh-trigger" onclick={openLineHeightPicker} title="Line &amp; paragraph spacing">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
+4
View File
@@ -5,6 +5,8 @@ import Bold from '@tiptap/extension-bold';
import Italic from '@tiptap/extension-italic';
import Underline from '@tiptap/extension-underline';
import Strike from '@tiptap/extension-strike';
import Subscript from '@tiptap/extension-subscript';
import Superscript from '@tiptap/extension-superscript';
import Highlight from '@tiptap/extension-highlight';
import { TextStyle, FontFamily, FontSize } from '@tiptap/extension-text-style';
import { FontWeight } from './fontWeight';
@@ -34,6 +36,8 @@ export const extensions = [
Italic,
Underline,
Strike,
Subscript,
Superscript,
TextStyle,
FontFamily,
FontSize,
+2
View File
@@ -552,6 +552,8 @@ function applyRuns(p: ParagraphBuilder | CellBuilder, content: TiptapNode[] = []
if (marks.some(m => m.type === 'italic')) fmt.italic = true;
if (marks.some(m => m.type === 'underline')) fmt.underline = true;
if (marks.some(m => m.type === 'strike')) fmt.strikethrough = true;
if (marks.some(m => m.type === 'superscript')) fmt.superscript = true;
else if (marks.some(m => m.type === 'subscript')) fmt.subscript = true;
if (tsm?.attrs?.fontFamily) {
const ff = String(tsm.attrs.fontFamily);
// Explicitly choosing the editor default should match the untagged