Giter Site home page Giter Site logo

doist / typist Goto Github PK

View Code? Open in Web Editor NEW
419.0 8.0 12.0 32.6 MB

The mighty Tiptap-based rich-text editor that powers Doist products.

Home Page: https://typist.doist.dev

License: MIT License

JavaScript 1.37% TypeScript 94.58% HTML 0.73% CSS 3.33%
editor markdown markdown-editor plain-text prosemirror react rich-text rich-text-editor text-editor tiptap

typist's Introduction

Typist is the mighty Tiptap-based rich-text editor React component that powers Doist products, which can also be used for displaying content in a read-only fashion. Typist also supports a plain-text mode, and comes with HTML/Markdown serializers.

Note

This project is not attempting to be an all-purpose rich-text editor. Whilst everyone is welcome to fork or use this package in their own products, development decisions are centered around Doist product requirements.

GitHub: CI Validation npm Version npm Bundle Size (minified) npm Downloads (monthly)

semantic-release: Conventional Commits Contributor Covenant License: MIT

Installation

npm install --save @doist/typist

Peer Dependencies

If you are using npm 7+ and the legacy-peer-deps options is not enabled, peer dependencies should have been automatically installed for you with the command above. Otherwise, you can install them with:

npm info @doist/typist peerDependencies --json \
    | command sed 's/[\{\},]//g ; s/: /@/g' \
    | xargs npm install --save

Usage

import { TypistEditor, RichTextKit } from '@doist/typist'

function TypistEditorContainer({ content }) {
    return (
        <TypistEditor
            placeholder="A full rich-text editor, be creative…"
            content={content}
            extensions={[RichTextKit]}
        />
    )
}

If you're looking for additional documentation, in-depth examples, or a live demo, please check out our Storybook.

Resources

A curated list of open-source rich-text editors powered by Tiptap that we can draw inspiration from:

Contributing

If you're interested in contributing code and/or documentation, please read our contributing guide.

License

The use of this source code is governed by an MIT-style license that can be found in the LICENSE file.

typist's People

Contributors

ayushanand18 avatar deorus avatar doistbot avatar frankieyan avatar gnapse avatar nats12 avatar pawelgrimm avatar pedroalves0 avatar renovate[bot] avatar rfgamaral avatar scottlovegrove avatar sndp-s avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

typist's Issues

Error: Cannot read properties of null (reading 'updateOuterDeco')

Bug description

While running the example presented on the README for this project in dev mode, the code threw the error below.

I tried to use the use-editor hook provided by Tiptap instead of the custom one for this project and the code ran well. I think the problem may be related to the fact that while hot-reloading, Tiptap tries to access a destroyed editor.

The use-editor hook was written more than a year ago, and since then Tiptap had multiple updates. Specifically, ueberdosis/tiptap#4000 might be related to it.

Error:

Cannot read properties of null (reading 'updateOuterDeco')
TypeError: Cannot read properties of null (reading 'updateOuterDeco')
    at EditorView.updateStateInner (http://localhost:3000/static/js/bundle.js:99248:24)
    at EditorView.update (http://localhost:3000/static/js/bundle.js:99181:10)
    at EditorView.setProps (http://localhost:3000/static/js/bundle.js:99193:10)
    at Editor.createNodeViews (http://localhost:3000/static/js/bundle.js:57999:15)
    at PureEditorContent.init (http://localhost:3000/static/js/bundle.js:62223:14)
    at PureEditorContent.componentDidMount (http://localhost:3000/static/js/bundle.js:62204:10)
    at invokeLayoutEffectMountInDEV (http://localhost:3000/static/js/bundle.js:36371:26)
    at invokeEffectsInDev (http://localhost:3000/static/js/bundle.js:38289:15)
    at commitDoubleInvokeEffectsInDEV (http://localhost:3000/static/js/bundle.js:38270:9)
    at flushPassiveEffectsImpl (http://localhost:3000/static/js/bundle.js:38045:9)

Version information:

Package version: 2.1.3
React: 18.2.0

Does not work with Next.js

"use client"

import { PlainTextKit } from "@doist/typist"

const TypistEditor = dynamic(() => import("@doist/typist").then((mod) => mod.TypistEditor), {
  ssr: false,
})

// ...Later in render()

<TypistEditor placeholder="A full rich-text editor, be creative…" content={value} extensions={[PlainTextKit]} />

result in error:

Unhandled Runtime Error
TypeError: this.docView is null

Pasting a URL on a text selection no longer hyperlinks the selection

With #411 we fixed Markdown hyperlink pasting which stopped working, however, that introduced this new issue where pasting a URL on a text selection no longer hyperlinks the selection. Instead, the text selection is completely replaced with the URL. This mechanism came from Tiptap, and with the recent updates, the mechanism was moved to the pasteHandler plugin, which got disabled with #411.

The fix for this issue involves reverting #411, and fixing the issue that #411 aimed to fix with a different solution.

One possible solution that I thought of was to implement the validate function from Linkify here, and test for the Markdown hyperlink syntax. If the Markdown hyperlink syntax is found, return false, otherwise return true. This fix will need to be pushed upstream to Tiptap. Also, it may be worth it to introduce a new option to the Link extension to allows users control over this behaviour.

However, the above solution does not work because there's a bug in the Linkify find function, which I reported here. Once that's fixed, and a new Linkify version is released, we can then start working on pushing a fix to Tiptap.

The upstream Tiptap issue is also reported here.

How to modify the selected suggestion node

Right now, we receive the markdown output of an @mention node as [mentioned_name](mention://ID) (ID being a number).
For my use case, I need

  1. An alphanumeric string as ID (Doing so currently results in NaN in the .md output )
  2. Replace the node with a custom node or provide a custom node in config
    Can someone please let me know how to achieve the goals listed above, Thanks.

References:
Where ID is given to the item:

Where item suggestion item created: https://github.com/Doist/typist/blob/main/src/factories/create-suggestion-extension.ts

Server rendering with Next.js 13

Hi, thanks for making this lib public :) I'm a big fan of everything you make at Doist!

I'm trying to get typist working in a next.js app. There are a few issues:

  • ESM imports — Next.js 13 supports module imports, but I can't seem to use import statements as shown in the typist docs. I get an unexpected keyword 'export' error.
  • Lazy imports — I can lazy load the editor component with next.js dynamic imports, but have had no luck lazily importing the typist presets for tiptap.

Are there any plans to support server rendering, or to improve the way modules are exported for compatibility?

Italic gets replaced by underscore characters if only parts of words are italic

Current behaviour

If I change parts of a sentence to italic, the correct/expected parts of the text look italic in the text editor, however once I submit the text an underscore character shows up and those parts of words are not actually rendered as italic:

249099120-129b2f25-5e6c-43b5-9742-0758b9bf7988.mp4

Expected behaviour

The text appears as italic even after submitting the text (and no underscores appear).

TypistEditor throwing errors when used in StrictMode

I tried writing a quick demo:

import { TypistEditor, RichTextKit } from '@doist/typist'

function TypistEditorContainer({ content }) {
  return (
      <TypistEditor
          placeholder="A full rich-text editor, be creative…"
          content={content}
          extensions={[RichTextKit]}
      />
  )
}
export default function App() {
  return (
    <div>
      <h1>doist typist demo</h1>
      <p>rich text editor</p>
      <TypistEditorContainer content=""/>
    </div>
  );
}

But I am receiving the following error

Error in /turbo_modules/[email protected]/dist/useEvent.js (38:11)
INVALID_USEEVENT_INVOCATION: the callback from useEvent cannot be invoked before the component has mounted.

The demo I wrote is hosted here: https://stackblitz.com/edit/react-n1taui?file=src%2FTypistEditorContainer.js,src%2FApp.js

Can someone please let know what is wrong with this?

formatting state not being updated as soon as change triggered

Overview

The formatting state is not being updated as soon as the button is clicked or a keyboard shortcut is used.
For e.g., When I press Ctrl+B or click the B (for bold) on the Rich Text Editor, it doesn't show it is turned on. The button is highlighted, suggesting turned on, only when I input the next letter from my keyboard.

Steps to reproduce

  1. Run npm run storybook:start or navigate to https://typist.doist.dev/
  2. Navigate to Rich-text-> Default from the left menu.
  3. Click on B or Ctrl+B/Cmd+B to toggle bold.
  4. Observation: The icon is not yet highlighted suggesting to the user that it didn't turn on. On all other major platforms the button turns on the moment the change is triggered.
  5. However, the next letter has the updated formatting (in bold) as per expectations.

Questions

  • Is this a design choice by the team? Because this behaviour is different from other major WYSIWYG editors like MS Word, Google Docs, LibreOffice Writer or even web-based editors (eg Froala https://froala.com/wysiwyg-editor/demo/).

If this is something the team is looking forward to, I can help contribute to a fix.

Thanks!

Editor (input field) loosing focus

Context: I have embedded 'typist' in my app which is a extension that attaches to Whatsapp Web.
The typist editor looses focus to whatsapp's chat editor as shown in the video below:

screen-capture-1.webm

The problem doesn't show up in isolated case Here is the snippet I am using in my project:

RichTextKit.configure({
  document: {
    multiline: false,
  },
});

function RichTextInput({ content, onUpdate }) {
  const typistEditorRef = useRef(null);

  const handleUpdate = useEvent(({ getMarkdown }) => {
    onUpdate(getMarkdown());
    typistEditorRef.focus();
  });

  return (
    <TypistEditor
      className="rich-text-input"
      content={content}
      extensions={[RichTextKit]}
      onUpdate={handleUpdate}
      ref={typistEditorRef}
    />
  );
}
<RichTextInput
  content={richTextInputContent}
  onUpdate={setRichTextInputContent}
/>

Here is a clip showing the behaviour with autoFocus prop
screen-capture-autoFocus.webm

Peer dependencies not installed automatically

Hello ,
thanks for the great library. I have some problems get in running. Here is my setup:

  • I am using npm V 10.2.4.
  • I use an .npmrc file with legacy-peer-deps=true
  • I am using webpack 5

Then I run

npm install --save @doist/typist

I implement the editor according to the docs. But after running webpack I get these errros.

  • ERROR in ./node_modules/@doist/typist/dist/hooks/use-editor.js 2:0-47
    Module not found: Error: Can't resolve '@react-hookz/web'
  • ERROR in ./node_modules/@doist/typist/dist/serializers/html/html.js 2:0-62
    Module not found: Error: Can't resolve 'rehype-minify-whitespace'
  • ERROR in ./node_modules/@doist/typist/dist/serializers/html/plugins/rehype-image.js 1:0-43
    Module not found: Error: Can't resolve 'unist-util-remove'
  • ERROR in ./node_modules/@doist/typist/dist/serializers/markdown/markdown.js 1:0-32
    Module not found: Error: Can't resolve 'turndown'

According to the docs the peer depedencies should be installed automatically. What do I need to do to do that?
Thanks for any advice

URL inside inline code is automatically converted into a link

With the introduction of #309, URL typed inside inline code blocks are automatically converted into links, which is most likely not the behaviour we want. At least it's not what I would expect, as I usually use inline code block to avoid URL->link conversion. The conversion happens after closing the code block and pressing space.

CleanShot.2023-06-22.at.22.54.59.mp4

Action Required: Fix Renovate Configuration

There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.

Error type: Cannot find preset's package (github>doist/renovate-config:frontend-base)

Links are lost on paste when their linked text include inline code

Take this markdown for example:

[`Hello` there](https://www.google.ca)

When it's being pasted into the rich text editor, the link itself is gone, leaving only the content behind when converted back to markdown:

`Hello` there

You could recreate the link using the link toolbar, but it results in something like this instead:

`Hello` [there](https://www.google.ca)

On GitHub, the inline code element is respected when making the whole string a link:

Hello there


This can be seen in our weekly bug rotation thread:

image

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Pending Status Checks

These updates await pending status checks. To force their creation now, click the checkbox below.

  • chore(deps): update storybook monorepo to v8.2.8 (@storybook/addon-a11y, @storybook/addon-essentials, @storybook/blocks, @storybook/manager-api, @storybook/react, @storybook/react-vite, storybook)
  • chore(deps): update dependency type-fest to v4.24.0

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

  • chore(deps): update linters (eslint-plugin-simple-import-sort, eslint-plugin-vitest, prettier)
  • fix(deps): update tiptap packages to v2.5.8 (@tiptap/core, @tiptap/extension-blockquote, @tiptap/extension-bold, @tiptap/extension-bullet-list, @tiptap/extension-character-count, @tiptap/extension-code, @tiptap/extension-code-block, @tiptap/extension-document, @tiptap/extension-dropcursor, @tiptap/extension-gapcursor, @tiptap/extension-hard-break, @tiptap/extension-heading, @tiptap/extension-history, @tiptap/extension-horizontal-rule, @tiptap/extension-image, @tiptap/extension-italic, @tiptap/extension-link, @tiptap/extension-list-item, @tiptap/extension-list-keymap, @tiptap/extension-ordered-list, @tiptap/extension-paragraph, @tiptap/extension-placeholder, @tiptap/extension-strike, @tiptap/extension-task-item, @tiptap/extension-task-list, @tiptap/extension-text, @tiptap/extension-text-style, @tiptap/extension-typography, @tiptap/pm, @tiptap/react, @tiptap/suggestion)
  • chore(deps): update dependency eslint to v9
  • Click on this checkbox to rebase all open PRs at once

Detected dependencies

npm
package.json
  • @tiptap/core 2.3.0
  • @tiptap/extension-blockquote 2.3.0
  • @tiptap/extension-bold 2.3.0
  • @tiptap/extension-bullet-list 2.3.0
  • @tiptap/extension-character-count 2.3.0
  • @tiptap/extension-code 2.3.0
  • @tiptap/extension-code-block 2.3.0
  • @tiptap/extension-document 2.3.0
  • @tiptap/extension-dropcursor 2.3.0
  • @tiptap/extension-gapcursor 2.3.0
  • @tiptap/extension-hard-break 2.3.0
  • @tiptap/extension-heading 2.3.0
  • @tiptap/extension-history 2.3.0
  • @tiptap/extension-horizontal-rule 2.3.0
  • @tiptap/extension-image 2.3.0
  • @tiptap/extension-italic 2.3.0
  • @tiptap/extension-link 2.3.0
  • @tiptap/extension-list-item 2.3.0
  • @tiptap/extension-list-keymap 2.3.0
  • @tiptap/extension-ordered-list 2.3.0
  • @tiptap/extension-paragraph 2.3.0
  • @tiptap/extension-placeholder 2.3.0
  • @tiptap/extension-strike 2.3.0
  • @tiptap/extension-task-item 2.3.0
  • @tiptap/extension-task-list 2.3.0
  • @tiptap/extension-text 2.3.0
  • @tiptap/extension-text-style 2.3.0
  • @tiptap/extension-typography 2.3.0
  • @tiptap/pm 2.3.0
  • @tiptap/react 2.3.0
  • @tiptap/suggestion 2.3.0
  • prosemirror-codemark 0.4.2
  • @doist/eslint-config 11.1.0
  • @doist/prettier-config 4.0.0
  • @doist/reactist 23.3.0
  • @mdx-js/react 3.0.1
  • @semantic-release/changelog 6.0.3
  • @semantic-release/exec 6.0.3
  • @semantic-release/git 10.0.1
  • @storybook/addon-a11y 8.2.7
  • @storybook/addon-essentials 8.2.7
  • @storybook/blocks 8.2.7
  • @storybook/csf 0.1.11
  • @storybook/manager-api 8.2.7
  • @storybook/mdx2-csf 1.1.0
  • @storybook/react 8.2.7
  • @storybook/react-vite 8.2.7
  • @testing-library/dom 10.4.0
  • @testing-library/jest-dom 6.4.8
  • @testing-library/react 16.0.0
  • @types/hast 3.0.4
  • @types/lodash-es 4.17.12
  • @types/react 18.3.3
  • @types/react-dom 18.3.0
  • @types/react-syntax-highlighter 15.5.13
  • @types/turndown 5.0.5
  • @types/unist 3.0.2
  • @vitejs/plugin-react 4.3.1
  • boring-avatars 1.10.2
  • classnames 2.5.1
  • conventional-changelog-conventionalcommits 8.0.0
  • emoji-regex 10.3.0
  • eslint 8.57.0
  • eslint-formatter-codeframe 7.32.1
  • eslint-import-resolver-typescript 3.6.1
  • eslint-plugin-simple-import-sort 12.0.0
  • eslint-plugin-storybook 0.8.0
  • eslint-plugin-unicorn 55.0.0
  • eslint-plugin-vitest 0.4.1
  • eslint-plugin-vitest-globals 1.5.0
  • github-markdown-css 5.6.1
  • husky 9.1.4
  • ignore-sync 7.0.1
  • is-ci 3.0.1
  • jsdom 24.1.1
  • lint-staged 15.2.8
  • npm-run-all2 6.2.2
  • prettier 3.2.5
  • react 18.3.1
  • react-dom 18.3.1
  • react-icons 5.2.1
  • react-markdown 9.0.1
  • react-syntax-highlighter 15.5.0
  • rehype-raw 7.0.0
  • remark-gfm 4.0.0
  • rimraf 6.0.1
  • semantic-release 24.0.0
  • storybook 8.2.7
  • storybook-css-modules 1.0.8
  • tippy.js 6.3.7
  • type-fest 4.23.0
  • typescript 5.5.4
  • typescript-plugin-css-modules 5.1.0
  • vitest 2.0.5
  • emoji-regex ^10.2.1
  • hast-util-is-element ^3.0.0
  • linkifyjs ^4.1.1
  • lodash-es ^4.17.21
  • mdast-util-gfm-autolink-literal ^2.0.0
  • mdast-util-gfm-strikethrough ^2.0.0
  • micromark-extension-gfm-autolink-literal ^2.0.0
  • micromark-extension-gfm-strikethrough ^2.0.0
  • react ^17.0.0 || ^18.0.0
  • react-dom ^17.0.0 || ^18.0.0
  • rehype ^13.0.0
  • rehype-minify-whitespace ^6.0.0
  • rehype-raw ^7.0.0
  • rehype-stringify ^10.0.0
  • remark ^15.0.0
  • remark-breaks ^4.0.0
  • remark-gfm ^4.0.0
  • remark-parse ^11.0.0
  • remark-rehype ^11.0.0
  • turndown ^7.1.0
  • unified ^11.0.0
  • unist-util-is ^6.0.0
  • unist-util-remove ^4.0.0
  • unist-util-visit ^5.0.0
  • node ^16.0.0 || ^18.0.0 || ^20.0.0 || ^21.0.0
  • npm ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0

  • Check this box to trigger a request for Renovate to run again on this repository

Override suggestion markdown serializer function.

My use case requires me to return a custom URL based on the ID string.
i.e. return something like `[${label}](matrix.to/${id})` instead of returning `[${label}](${attributeType}://${id})`

Thank you

support for Node v19^

Overview

Thanks for the great library!
I tried installing it on my environment however, since my Node version is 19.9.0 the install failed because the engine was not supported. I get this error.

$ npm install
npm WARN ERESOLVE overriding peer dependency
npm WARN ERESOLVE overriding peer dependency
npm WARN ERESOLVE overriding peer dependency
npm WARN ERESOLVE overriding peer dependency
npm WARN ERESOLVE overriding peer dependency
npm WARN ERESOLVE overriding peer dependency
npm ERR! code EBADENGINE
npm ERR! engine Unsupported engine
npm ERR! engine Not compatible with your version of node/npm: @doist/[email protected]
npm ERR! notsup Not compatible with your version of node/npm: @doist/[email protected]
npm ERR! notsup Required: {"node":"^16.0.0 || ^18.0.0","npm":"^8.3.0 || ^9.0.0"}
npm ERR! notsup Actual:   {"npm":"9.6.3","node":"v19.9.0"}

Is the team planning to add support v19+?

Additional Details

details version
node 19.9.0
npm 9.6.3

Thanks!

Images copied from the browser are pasted as inline links rather than handled via `onImageFilePaste`

Not sure if this is truly a bug, but when you copy an image from the browser and paste it into the composer, it shows up as an inline image that is sourced from the original URL, instead of being uploaded (via onImageFilePaste).

This is somewhat of a problem if the URL requires authentication, such as when copied from GitHub. It's also a bit inconsistent compared to other instances of inline images where they are always uploaded to our servers. The same image copied from a browser but pasted to other desktop apps (e.g. Signal, Whatsapp) often end up being uploaded as well.

For our users, this may not be very transparent because the pasted image will likely still be viewable by them, and they'd only realize a problem if they inspect the URL of the image.

Reproduction

image

Additional information

Clipboard data from https://evercoder.github.io/clipboard-inspector/
image

It's possible that this conflicts with the solution we have in place to prevent tabular data copied from Numbers from pasting an image: #290

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.