Skip to content

Commit 3b4e06c

Browse files
authored
feat(font-size): add font size extension (#5894)
1 parent 20f68f6 commit 3b4e06c

File tree

15 files changed

+354
-0
lines changed

15 files changed

+354
-0
lines changed

.changeset/red-rivers-exist.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@tiptap/extension-font-size": patch
3+
---
4+
5+
This adds the new @tiptap/extension-font-size extension for changing the font-size of text based on the textStyle extension

.vscode/settings.json

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"extension/floating-menu",
2323
"extension/focus",
2424
"extension/font-family",
25+
"extension/font-size",
2526
"extension/gapcursor",
2627
"extension/hard-break",
2728
"extension/heading",

demos/src/Extensions/FontSize/React/index.html

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import FontSize from '@tiptap/extension-font-size'
2+
import TextStyle from '@tiptap/extension-text-style'
3+
import { EditorContent, useEditor } from '@tiptap/react'
4+
import StarterKit from '@tiptap/starter-kit'
5+
6+
export default () => {
7+
const editor = useEditor({
8+
shouldRerenderOnTransaction: true,
9+
extensions: [StarterKit, TextStyle, FontSize],
10+
content: `
11+
<p>Adjusting font sizes can greatly affect the readability of your text, making it easier for users to engage with your content.</p>
12+
<p>When designing a website, it's crucial to balance large headings and smaller body text for a clean, organized layout.</p>
13+
<p>When setting font sizes, it's important to consider accessibility, ensuring that text is readable for users with different visual impairments.</p>
14+
<p><span style="font-size: 10px">Too small</span> a font size can strain the eyes, while <span style="font-size: 40px">too large</span> can disrupt the flow of the design.</p>
15+
<p>When designing for mobile, font sizes should be adjusted to maintain readability on smaller screens.</p>
16+
`,
17+
})
18+
19+
if (!editor) {
20+
return null
21+
}
22+
23+
return <>
24+
<div className="control-group">
25+
<div className="button-group">
26+
<button
27+
onClick={() => editor.chain().focus().setFontSize('28px').run()}
28+
className={editor.isActive('textStyle', { fontSize: '28px' }) ? 'is-active' : ''}
29+
data-test-id="28px"
30+
>
31+
Font size 28px
32+
</button>
33+
<button
34+
onClick={() => editor.chain().focus().setFontSize('32px').run()}
35+
className={editor.isActive('textStyle', { fontSize: '32px' }) ? 'is-active' : ''}
36+
data-test-id="32px"
37+
>
38+
Font size 32px
39+
</button>
40+
<button
41+
onClick={() => editor.chain().focus().unsetFontSize().run()}
42+
data-test-id="unsetFontSize"
43+
>
44+
Unset font size
45+
</button>
46+
</div>
47+
</div>
48+
49+
<EditorContent editor={editor} />
50+
</>
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
context('/src/Extensions/FontSize/React/', () => {
2+
before(() => {
3+
cy.visit('/src/Extensions/FontSize/React/')
4+
})
5+
6+
beforeEach(() => {
7+
cy.get('.tiptap').then(([{ editor }]) => {
8+
editor.commands.setContent('<p>Example Text</p>')
9+
})
10+
cy.get('.tiptap').type('{selectall}')
11+
})
12+
13+
it('should set the font-size of the selected text', () => {
14+
cy.get('[data-test-id="28px"]')
15+
.should('not.have.class', 'is-active')
16+
.click()
17+
.should('have.class', 'is-active')
18+
19+
cy.get('.tiptap').find('span').should('have.attr', 'style', 'font-size: 28px')
20+
})
21+
22+
it('should remove the font-size of the selected text', () => {
23+
cy.get('[data-test-id="28px"]').click()
24+
cy.get('.tiptap').find('span').should('have.attr', 'style', 'font-size: 28px')
25+
cy.get('[data-test-id="unsetFontSize"]').click()
26+
cy.get('.tiptap').get('span').should('not.exist')
27+
})
28+
})

demos/src/Extensions/FontSize/Vue/index.html

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
context('/src/Extensions/FontSize/Vue/', () => {
2+
before(() => {
3+
cy.visit('/src/Extensions/FontSize/Vue/')
4+
})
5+
6+
beforeEach(() => {
7+
cy.get('.tiptap').then(([{ editor }]) => {
8+
editor.commands.setContent('<p>Example Text</p>')
9+
})
10+
cy.get('.tiptap').type('{selectall}')
11+
})
12+
13+
it('should set the font-size of the selected text', () => {
14+
cy.get('[data-test-id="28px"]')
15+
.should('not.have.class', 'is-active')
16+
.click()
17+
.should('have.class', 'is-active')
18+
19+
cy.get('.tiptap').find('span').should('have.attr', 'style', 'font-size: 28px')
20+
})
21+
22+
it('should remove the font-size of the selected text', () => {
23+
cy.get('[data-test-id="28px"]').click()
24+
cy.get('.tiptap').find('span').should('have.attr', 'style', 'font-size: 28px')
25+
cy.get('[data-test-id="unsetFontSize"]').click()
26+
cy.get('.tiptap').get('span').should('not.exist')
27+
})
28+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<template>
2+
<div v-if="editor" class="container">
3+
<div class="control-group">
4+
<div class="button-group">
5+
<button @click="editor.chain().focus().setFontSize('28px').run()" :class="{ 'is-active': editor.isActive('textStyle', { fontSize: '28px' }) }" data-test-id="28px">
6+
Font size 28px
7+
</button>
8+
<button @click="editor.chain().focus().setFontSize('32px').run()" :class="{ 'is-active': editor.isActive('textStyle', { fontSize: '32px' }) }" data-test-id="32px">
9+
Font size 32px
10+
</button>
11+
<button @click="editor.chain().focus().unsetFontSize().run()" data-test-id="unsetFontSize">
12+
Unset font size
13+
</button>
14+
</div>
15+
</div>
16+
<editor-content :editor="editor" />
17+
</div>
18+
</template>
19+
20+
<script>
21+
import FontSize from '@tiptap/extension-font-size'
22+
import TextStyle from '@tiptap/extension-text-style'
23+
import StarterKit from '@tiptap/starter-kit'
24+
import { Editor, EditorContent } from '@tiptap/vue-3'
25+
26+
export default {
27+
components: {
28+
EditorContent,
29+
},
30+
31+
data() {
32+
return {
33+
editor: null,
34+
}
35+
},
36+
37+
mounted() {
38+
this.editor = new Editor({
39+
extensions: [
40+
StarterKit,
41+
TextStyle,
42+
FontSize,
43+
],
44+
content: `
45+
<p>Adjusting font sizes can greatly affect the readability of your text, making it easier for users to engage with your content.</p>
46+
<p>When designing a website, it's crucial to balance large headings and smaller body text for a clean, organized layout.</p>
47+
<p>When setting font sizes, it's important to consider accessibility, ensuring that text is readable for users with different visual impairments.</p>
48+
<p><span style="font-size: 10px">Too small</span> a font size can strain the eyes, while <span style="font-size: 40px">too large</span> can disrupt the flow of the design.</p>
49+
<p>When designing for mobile, font sizes should be adjusted to maintain readability on smaller screens.</p>
50+
`,
51+
})
52+
},
53+
54+
beforeUnmount() {
55+
this.editor.destroy()
56+
},
57+
}
58+
</script>

package-lock.json

+21
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Change Log
2+
3+
## 2.10.2
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# @tiptap/extension-font-size
2+
[![Version](https://img.shields.io/npm/v/@tiptap/extension-font-size.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-font-size)
3+
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-font-size.svg)](https://npmcharts.com/compare/tiptap?minimal=true)
4+
[![License](https://img.shields.io/npm/l/@tiptap/extension-font-size.svg)](https://www.npmjs.com/package/@tiptap/extension-font-size)
5+
[![Sponsor](https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub)](https://github.com/sponsors/ueberdosis)
6+
7+
## Introduction
8+
Tiptap is a headless wrapper around [ProseMirror](https://ProseMirror.net) – a toolkit for building rich text WYSIWYG editors, which is already in use at many well-known companies such as *New York Times*, *The Guardian* or *Atlassian*.
9+
10+
## Official Documentation
11+
Documentation can be found on the [Tiptap website](https://tiptap.dev).
12+
13+
## License
14+
Tiptap is open sourced software licensed under the [MIT license](https://github.com/ueberdosis/tiptap/blob/main/LICENSE.md).
+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
{
2+
"name": "@tiptap/extension-font-size",
3+
"description": "font size extension for tiptap",
4+
"version": "3.0.0-next.3",
5+
"homepage": "https://tiptap.dev",
6+
"keywords": [
7+
"tiptap",
8+
"tiptap extension"
9+
],
10+
"license": "MIT",
11+
"funding": {
12+
"type": "github",
13+
"url": "https://github.com/sponsors/ueberdosis"
14+
},
15+
"type": "module",
16+
"exports": {
17+
".": {
18+
"types": "./dist/index.d.ts",
19+
"import": "./dist/index.js",
20+
"require": "./dist/index.cjs"
21+
}
22+
},
23+
"main": "dist/index.cjs",
24+
"module": "dist/index.js",
25+
"types": "dist/index.d.ts",
26+
"files": [
27+
"src",
28+
"dist"
29+
],
30+
"devDependencies": {
31+
"@tiptap/core": "^3.0.0-next.3",
32+
"@tiptap/extension-text-style": "^3.0.0-next.3"
33+
},
34+
"peerDependencies": {
35+
"@tiptap/core": "^3.0.0-next.3",
36+
"@tiptap/extension-text-style": "^3.0.0-next.3"
37+
},
38+
"repository": {
39+
"type": "git",
40+
"url": "https://github.com/ueberdosis/tiptap",
41+
"directory": "packages/extension-font-size"
42+
},
43+
"scripts": {
44+
"build": "tsup"
45+
}
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import '@tiptap/extension-text-style'
2+
3+
import { Extension } from '@tiptap/core'
4+
5+
export type FontSizeOptions = {
6+
/**
7+
* A list of node names where the font size can be applied.
8+
* @default ['textStyle']
9+
* @example ['heading', 'paragraph']
10+
*/
11+
types: string[];
12+
};
13+
14+
declare module '@tiptap/core' {
15+
interface Commands<ReturnType> {
16+
fontSize: {
17+
/**
18+
* Set the font size
19+
* @param fontSize The font size
20+
* @example editor.commands.setFontSize('Arial')
21+
*/
22+
setFontSize: (fontSize: string) => ReturnType;
23+
/**
24+
* Unset the font size
25+
* @example editor.commands.unsetFontSize()
26+
*/
27+
unsetFontSize: () => ReturnType;
28+
};
29+
}
30+
}
31+
32+
/**
33+
* This extension allows you to set a font size for text.
34+
* @see https://www.tiptap.dev/api/extensions/font-size
35+
*/
36+
export const FontSize = Extension.create<FontSizeOptions>({
37+
name: 'fontSize',
38+
39+
addOptions() {
40+
return {
41+
types: ['textStyle'],
42+
}
43+
},
44+
45+
addGlobalAttributes() {
46+
return [
47+
{
48+
types: this.options.types,
49+
attributes: {
50+
fontSize: {
51+
default: null,
52+
parseHTML: element => element.style.fontSize,
53+
renderHTML: attributes => {
54+
if (!attributes.fontSize) {
55+
return {}
56+
}
57+
58+
return {
59+
style: `font-size: ${attributes.fontSize}`,
60+
}
61+
},
62+
},
63+
},
64+
},
65+
]
66+
},
67+
68+
addCommands() {
69+
return {
70+
setFontSize:
71+
fontSize => ({ chain }) => {
72+
return chain().setMark('textStyle', { fontSize }).run()
73+
},
74+
unsetFontSize:
75+
() => ({ chain }) => {
76+
return chain().setMark('textStyle', { fontSize: null }).removeEmptyTextStyle().run()
77+
},
78+
}
79+
},
80+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { FontSize } from './font-size.js'
2+
3+
export * from './font-size.js'
4+
5+
export default FontSize
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { defineConfig } from 'tsup'
2+
3+
export default defineConfig({
4+
entry: ['src/index.ts'],
5+
tsconfig: '../../tsconfig.build.json',
6+
outDir: 'dist',
7+
dts: true,
8+
clean: true,
9+
sourcemap: true,
10+
format: [
11+
'esm',
12+
'cjs',
13+
],
14+
})

0 commit comments

Comments
 (0)