Skip to content
New issue

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

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

[ISSUE-5815] Add font size extension #5894

Merged
merged 8 commits into from
Dec 31, 2024
Merged
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
5 changes: 5 additions & 0 deletions .changeset/red-rivers-exist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@tiptap/extension-font-size": patch
---

This adds the new @tiptap/extension-font-size extension for changing the font-size of text based on the textStyle extension
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"extension/floating-menu",
"extension/focus",
"extension/font-family",
"extension/font-size",
"extension/gapcursor",
"extension/hard-break",
"extension/heading",
Expand Down
Empty file.
51 changes: 51 additions & 0 deletions demos/src/Extensions/FontSize/React/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import FontSize from '@tiptap/extension-font-size'
import TextStyle from '@tiptap/extension-text-style'
import { EditorContent, useEditor } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'

export default () => {
const editor = useEditor({
shouldRerenderOnTransaction: true,
extensions: [StarterKit, TextStyle, FontSize],
content: `
<p>Adjusting font sizes can greatly affect the readability of your text, making it easier for users to engage with your content.</p>
<p>When designing a website, it's crucial to balance large headings and smaller body text for a clean, organized layout.</p>
<p>When setting font sizes, it's important to consider accessibility, ensuring that text is readable for users with different visual impairments.</p>
<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>
<p>When designing for mobile, font sizes should be adjusted to maintain readability on smaller screens.</p>
`,
})

if (!editor) {
return null
}

return <>
<div className="control-group">
<div className="button-group">
<button
onClick={() => editor.chain().focus().setFontSize('28px').run()}
className={editor.isActive('textStyle', { fontSize: '28px' }) ? 'is-active' : ''}
data-test-id="28px"
>
Font size 28px
</button>
<button
onClick={() => editor.chain().focus().setFontSize('32px').run()}
className={editor.isActive('textStyle', { fontSize: '32px' }) ? 'is-active' : ''}
data-test-id="32px"
>
Font size 32px
</button>
<button
onClick={() => editor.chain().focus().unsetFontSize().run()}
data-test-id="unsetFontSize"
>
Unset font size
</button>
</div>
</div>

<EditorContent editor={editor} />
</>
}
28 changes: 28 additions & 0 deletions demos/src/Extensions/FontSize/React/index.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
context('/src/Extensions/FontSize/React/', () => {
before(() => {
cy.visit('/src/Extensions/FontSize/React/')
})

beforeEach(() => {
cy.get('.tiptap').then(([{ editor }]) => {
editor.commands.setContent('<p>Example Text</p>')
})
cy.get('.tiptap').type('{selectall}')
})

it('should set the font-size of the selected text', () => {
cy.get('[data-test-id="28px"]')
.should('not.have.class', 'is-active')
.click()
.should('have.class', 'is-active')

cy.get('.tiptap').find('span').should('have.attr', 'style', 'font-size: 28px')
})

it('should remove the font-size of the selected text', () => {
cy.get('[data-test-id="28px"]').click()
cy.get('.tiptap').find('span').should('have.attr', 'style', 'font-size: 28px')
cy.get('[data-test-id="unsetFontSize"]').click()
cy.get('.tiptap').get('span').should('not.exist')
})
})
Empty file.
28 changes: 28 additions & 0 deletions demos/src/Extensions/FontSize/Vue/index.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
context('/src/Extensions/FontSize/Vue/', () => {
before(() => {
cy.visit('/src/Extensions/FontSize/Vue/')
})

beforeEach(() => {
cy.get('.tiptap').then(([{ editor }]) => {
editor.commands.setContent('<p>Example Text</p>')
})
cy.get('.tiptap').type('{selectall}')
})

it('should set the font-size of the selected text', () => {
cy.get('[data-test-id="28px"]')
.should('not.have.class', 'is-active')
.click()
.should('have.class', 'is-active')

cy.get('.tiptap').find('span').should('have.attr', 'style', 'font-size: 28px')
})

it('should remove the font-size of the selected text', () => {
cy.get('[data-test-id="28px"]').click()
cy.get('.tiptap').find('span').should('have.attr', 'style', 'font-size: 28px')
cy.get('[data-test-id="unsetFontSize"]').click()
cy.get('.tiptap').get('span').should('not.exist')
})
})
58 changes: 58 additions & 0 deletions demos/src/Extensions/FontSize/Vue/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<template>
<div v-if="editor" class="container">
<div class="control-group">
<div class="button-group">
<button @click="editor.chain().focus().setFontSize('28px').run()" :class="{ 'is-active': editor.isActive('textStyle', { fontSize: '28px' }) }" data-test-id="28px">
Font size 28px
</button>
<button @click="editor.chain().focus().setFontSize('32px').run()" :class="{ 'is-active': editor.isActive('textStyle', { fontSize: '32px' }) }" data-test-id="32px">
Font size 32px
</button>
<button @click="editor.chain().focus().unsetFontSize().run()" data-test-id="unsetFontSize">
Unset font size
</button>
</div>
</div>
<editor-content :editor="editor" />
</div>
</template>

<script>
import FontSize from '@tiptap/extension-font-size'
import TextStyle from '@tiptap/extension-text-style'
import StarterKit from '@tiptap/starter-kit'
import { Editor, EditorContent } from '@tiptap/vue-3'

export default {
components: {
EditorContent,
},

data() {
return {
editor: null,
}
},

mounted() {
this.editor = new Editor({
extensions: [
StarterKit,
TextStyle,
FontSize,
],
content: `
<p>Adjusting font sizes can greatly affect the readability of your text, making it easier for users to engage with your content.</p>
<p>When designing a website, it's crucial to balance large headings and smaller body text for a clean, organized layout.</p>
<p>When setting font sizes, it's important to consider accessibility, ensuring that text is readable for users with different visual impairments.</p>
<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>
<p>When designing for mobile, font sizes should be adjusted to maintain readability on smaller screens.</p>
`,
})
},

beforeUnmount() {
this.editor.destroy()
},
}
</script>
21 changes: 21 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions packages/extension-font-size/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Change Log

## 2.10.2
14 changes: 14 additions & 0 deletions packages/extension-font-size/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# @tiptap/extension-font-size
[![Version](https://img.shields.io/npm/v/@tiptap/extension-font-size.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-font-size)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-font-size.svg)](https://npmcharts.com/compare/tiptap?minimal=true)
[![License](https://img.shields.io/npm/l/@tiptap/extension-font-size.svg)](https://www.npmjs.com/package/@tiptap/extension-font-size)
[![Sponsor](https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub)](https://github.com/sponsors/ueberdosis)

## Introduction
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*.

## Official Documentation
Documentation can be found on the [Tiptap website](https://tiptap.dev).

## License
Tiptap is open sourced software licensed under the [MIT license](https://github.com/ueberdosis/tiptap/blob/main/LICENSE.md).
46 changes: 46 additions & 0 deletions packages/extension-font-size/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"name": "@tiptap/extension-font-size",
"description": "font size extension for tiptap",
"version": "3.0.0-next.3",
"homepage": "https://tiptap.dev",
"keywords": [
"tiptap",
"tiptap extension"
],
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"type": "module",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"require": "./dist/index.cjs"
}
},
"main": "dist/index.cjs",
"module": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
"src",
"dist"
],
"devDependencies": {
"@tiptap/core": "^3.0.0-next.3",
"@tiptap/extension-text-style": "^3.0.0-next.3"
},
"peerDependencies": {
"@tiptap/core": "^3.0.0-next.3",
"@tiptap/extension-text-style": "^3.0.0-next.3"
},
"repository": {
"type": "git",
"url": "https://github.com/ueberdosis/tiptap",
"directory": "packages/extension-font-size"
},
"scripts": {
"build": "tsup"
}
}
80 changes: 80 additions & 0 deletions packages/extension-font-size/src/font-size.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import '@tiptap/extension-text-style'

import { Extension } from '@tiptap/core'

export type FontSizeOptions = {
/**
* A list of node names where the font size can be applied.
* @default ['textStyle']
* @example ['heading', 'paragraph']
*/
types: string[];
};

declare module '@tiptap/core' {
interface Commands<ReturnType> {
fontSize: {
/**
* Set the font size
* @param fontSize The font size
* @example editor.commands.setFontSize('Arial')
*/
setFontSize: (fontSize: string) => ReturnType;
/**
* Unset the font size
* @example editor.commands.unsetFontSize()
*/
unsetFontSize: () => ReturnType;
};
}
}

/**
* This extension allows you to set a font size for text.
* @see https://www.tiptap.dev/api/extensions/font-size
*/
export const FontSize = Extension.create<FontSizeOptions>({
name: 'fontSize',

addOptions() {
return {
types: ['textStyle'],
}
},

addGlobalAttributes() {
return [
{
types: this.options.types,
attributes: {
fontSize: {
default: null,
parseHTML: element => element.style.fontSize,
renderHTML: attributes => {
if (!attributes.fontSize) {
return {}
}

return {
style: `font-size: ${attributes.fontSize}`,
}
},
},
},
},
]
},

addCommands() {
return {
setFontSize:
fontSize => ({ chain }) => {
return chain().setMark('textStyle', { fontSize }).run()
},
unsetFontSize:
() => ({ chain }) => {
return chain().setMark('textStyle', { fontSize: null }).removeEmptyTextStyle().run()
},
}
},
})
5 changes: 5 additions & 0 deletions packages/extension-font-size/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { FontSize } from './font-size.js'

export * from './font-size.js'

export default FontSize
14 changes: 14 additions & 0 deletions packages/extension-font-size/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { defineConfig } from 'tsup'

export default defineConfig({
entry: ['src/index.ts'],
tsconfig: '../../tsconfig.build.json',
outDir: 'dist',
dts: true,
clean: true,
sourcemap: true,
format: [
'esm',
'cjs',
],
})
Loading