remirror

ProseMirror toolkit for React 🎉

MIT License

Downloads
14.7M
Stars
2.6K
Committers
81

Bot releases are hidden (Show)

remirror - Remirror v3 Beta 🎉

Published by whawker 11 months ago

TLDR: Remirror aims to be a better citizen, by not imposing our architectural decisions on to you.

🧐 Why?

This version aims to make it easier to use Remirror in existing applications, by not imposing our architectural decisions on to you.

The core of Remirror v2 relied on packages such as @mui/material to power our menus and toolbars, and @lingui/core to provide internationalisation (i18n) support.

However, after gathering feedback from the Remirror community, we found that most users wanted to integrate Remirror into existing applications, where design systems were already in place, and i18n solutions already present.

This meant Remirror's core created unnecessary pain points - translations needed to be encoded specifically for Remirror, in a different way to the rest of the application. For other users the menus we provided didn't fit with their application's existing design system, so Remirror ended up bloating the application unnecessarily with MUI components that weren't even used.

To alleviate these pain points we have removed these features from the core, and moved them into optional packages.

This enables Remirror to continue to support its main goal:

[!NOTE]
Remirror goal: "From Newbie to Pro"
Designed to grow with your skill set. Start with the out-of-the-box editor. Customize with components, React hooks, down to bare metal ProseMirror.

Our "out-of-the-box" editors (components exposed via @remirror/react-editors) include these new optional packages by default, so should have no breaking changes.

However, for more advanced scenarios we can use our Lego principle, allowing Remirror users to choose modules that make sense for their use case and build bespoke experiences for their applications.

✨ What's new?

Internationalisation changes

[!NOTE]
"Out-of-the-box" (@remirror/react-editors) editors unaffected, these have been updated to keep v2 behaviour.

In Remirror v3, we want to allow any i18n library to be used with Remirror, instead of forcing Lingui upon you.

The root <Remirror /> component now supports an i18nFormat prop, that allows you to plug in any i18n library, by implementing a definition for this function.

If you want to keep the existing behaviour from v2, you can pass the i18nFormat function exposed from the now optional package @remirror/i18n

We have Storybook examples showing integrations with many populate i18n libraries, and our "How to migrate" section below.

Menu and Toolbar changes

[!NOTE]
"Out-of-the-box" (@remirror/react-editors) editors unaffected, these have been updated to keep v2 behaviour.

Remirror v3 decouples the React core of Remirror from MUI, reducing the size of @remirror/react considerably, as installing @remirror/react will no longer bundle @mui/material too

The MUI components (menus and toolbars) previously exposed by @remirror/react have been moved to a new optional package - @remirror/react-ui.

Additionally, these MUI components should now adhere to the theme of the parent application, if you're already using MUI.

The components themselves should have no breaking changes, only their import paths have changed.

For a full list of affected components, please see our "How to migrate" section below.

Built-in decorators updated

[!NOTE]
This is an internal change, there should be no breaking changes to the public API.

Our decorators (i.e. @extension, @command, @keyBinding, etc), have been updated to use ES Stage-3 decorators syntax, instead of TypeScript's experimental decorator syntax.

Mention atoms as plain text

We've made a small change to ensure mention atoms are included in plain text by returning their label attribute value.

This can be modified using the nodeOverrides API and overriding the leafText function.

Removal of deprecated features

Remirror v3 also removes deprecated features, but in the vast majority of changes alternatives exist. We have highlighted a few of the key removals below, but the rest with be covered in the migration guide

SearchExtension removed, please use FindExtension instead

The FindExtension moves out of beta and into the core, as it offers more features and is more performant than the removed SearchExtension.

Furthermore, to make the find functionality easy to use, we have added a new <FindButton /> component to the optional @remirror/react-ui package.

This button can be used within a Toolbar (also exposed via @remirror/react-ui) to present a find and replace popup in the top right of your editor.

A screenshot of the find and replace popup from the FindButton

Command "dry run" function isEnabled removed, use enabled instead

When using commands or chained commands, you can "dry run" the command to see if it can be executed against the current editor state.

For instance, you can check if toggleBold is enabled by running toggleBold.enabled() which returns a boolean indicating whether it is possible, without actually changing the editor's state.

.isEnabled() was an alias of .enabled(), but this alias has now been removed. Please use .enabled() instead.

⬆️ How to migrate?

Please consult the migration guide and reach out on Discord if you run into any issues.

👂 Feedback

As this is a beta version we'd really love your feedback to check everything works as expected. Please raise any issues on GitHub or via our Discord server.

As always, reach out to use via our Discord server if you have any suggestions on how we could improve Remirror in general.

remirror - v1.0.7

Published by whawker about 3 years ago

Patch Changes

remirror - v1.0.6

Published by ifiokjr about 3 years ago

Patch Changes

  • #1055 b288d665f Thanks @ocavue! - Fix a crash when the code block node contains an invalid language name in @remirror/extension-code-block.
remirror - v1.0.0

Published by ifiokjr over 3 years ago

The new version of remirror comes with a number of enhancements and quite a few breaking changes if you were using the [email protected].* pre-releases.

The following sections outline the breaking changes and how they can be migrated if your last version was @next. For those upgrading from 0.11.0 the library has changed drastically and you'd be better off browsing the documentation.

Changes

All extensions are available via remirror/extensions

When you install the top level remirror package you are given access to every extension developed by remirror via the remirror/extension entry point.

- import { BoldExtension } from 'remirror/extension/bold';
- import { ItalicExtension } from 'remirror/extension/italic';
+ import { BoldExtension, ItalicExtension } from 'remirror/extensions';

You can also still install the extensions directly from their scoped packages.

import { BoldExtension } from '@remirror/extension-bold';

Remove remirror/react which has been replaced by @remirror/react

If your code is importing from remirror/react you should now change the import to @remirror/react.

- import { useManager } from 'remirror/react';
+ import { useRemirror } from '@remirror/react';

Update the @remirror/react API

  • Rename the original useRemirror to now be called useRemirrorContext.
  • Add new @remirror/react-components package.
  • @remirror/react exports all the hooks, components, core modules and react specific extensions from @remirror/react-core, @remirror/react-components, @remirror/react-hooks and @remirror/extension-react.

useManager was too focused on the implementation details. We've updated the API to be used in a different way and useRemirror is now the way to initialize an editor.

import React from 'react';
import { BoldExtension, ItalicExtension, UnderlineExtension } from 'remirror/extensions';
import { Remirror, useRemirror } from '@remirror/react';

const extensions = () => [new BoldExtension(), new ItalicExtension(), new UnderlineExtension()];

const Editor = () => {
  const { manager } = useRemirror({ extensions });

  return <Remirror manager={manager} />;
};

The previous useRemirror is now called useRemirrorContext since it plucks the context from the outer Remirror Component. The <RemirrorProvider /> has been renamed to <Remirror /> and automatically renders an editor.

When no children are provided to the <Remirror /> component it will automatically render a container div where the prosemirror editor will be placed. If you do add children it is up to you to import the <EditorComponent /> and add it to the children or set the autoRender prop to 'start' | 'end' | true.

useManager has been marked as @internal (although it is still exported) and going forward you should be using useRemirror as shown in the above example.

@remirror/extension-tables

@remirror/preset-table is now @remirror/extension-tables. The TableExtension uses the new createExtension method to inject the TableRowExtension which in turn injects the TableCellExtension and TableHeaderCellExtension. To use tables in your editor the following is sufficient.

import { TableExtension } from 'remirror/extensions';
import { Remirror, useRemirror } from '@remirror/react';

const Editor = () => {
  const { manager } = useRemirror({ extensions: () => [TableExtension()] });

  return <Remirror manager={manager} />;
};

@remirror/extension-positioner

  • New Rect interface returned by the positioner x: number; y: number; width: number; height: number;

  • Added visible property which shows if the position currently visible within the editor viewport.

  • Improved scrolling when using the positioner.

  • Fixed a lot of bugs in the positioner API.

  • This DOMRect represents an absolute position within the document. It is up to your consuming component to consume the rect.

  • Renamed the positioners in line with the new functionality.

import React from 'react';
import { BoldExtension, CorePreset, ItalicExtension, MarkdownExtension } from 'remirror/extension';
import { Remirror, useRemirror } from '@remirror/react';

const Editor = () => {
  const { manager, onChange, state } = useRemirror({
    extensions: () => [new BoldExtension(), new ItalicExtension()],
    content: '<p><strong>I am strong.</strong> and <em>I am emphasized</em></p>',
    stringHandler: 'html',
  });

  return <Remirror manager={manager} onChange={onChange} state={state} />;
};

@remirror/react-hooks

  • Rename useKeymap to useKeymaps. The original useKeymap now has a different signature.
import { useCallback } from 'react';
import { BoldExtension } from 'remirror/extensions';
import { Remirror, useHelpers, useKeymap, useRemirror, useRemirrorContext } from '@remirror/react';

const hooks = [
  () => {
    const active = useActive();
    const { insertText } = useCommands();
    const boldActive = active.bold();
    const handler = useCallback(() => {
      if (!boldActive) {
        return false;
      }

      return insertText.original('\n\nWoah there!')(props);
    }, [boldActive, insertText]);

    useKeymap('Shift-Enter', handler); // Add the handler to the keypress pattern.
  },
];

const Editor = () => {
  const { manager } = useRemirror({ extensions: () => [new BoldExtension()] });

  return <Remirror manager={manager} hooks={hooks} />;
};

Breaking Changes

  • Editor selection now defaults to the end of the document. You can change the starting point as shown below.

    import { Remirror, useRemirror } from '@remirror/react';
    
    const Editor = () => {
      const { manager, state } = useRemirror({ selection: 'start' });
    
      return <Remirror manger={manager} initialState={state} />;
    };
    
  • All interfaces which were named with the pattern *Parameter have been renamed to to *Props. The only exceptions are *FrameworkParameter which are now *FrameworkOptions.

  • Remove Presets completely. In their place a function that returns a list of Extensions should be used. They were clunky, difficult to use and provided little to no value.

  • Remove @remirror/core entry-point and add all core exports to the main remirror entry-point.

  • Add all Extensions and Preset package exports to the remirror/extensions subdirectory. It doesn't include framework specific exports which are made available from @remirror/react.

  • Rename @remirror/preset-table to @remirror/extension-tables.

  • Rename preset-list to extension-lists. ListPreset is now BulletListExtension and OrderListExtension.

  • Create new decorator pattern for adding @commands, @helper functions and @keyBindings.

  • Deprecate tags property on extension and encourage the use of createTags which is a method instead.

  • Rename interface CreatePluginReturn to CreateExtensionPlugin.

  • Add support for directly updating the doc attributes.

  • Deprecate top level context methods focus and blur. They should now be consumed as commands.

Removed Packages

The following packages have been removed.

  • Remove @remirror/showcase
  • Remove @remirror/react-social
  • Remove @remirror/react-wysiwyg
  • Remove package @remirror/extension-auto-link. The functionality is now self-contained within @remirror/extension-link.

ExtensionStore

Extensions

  • New createDecorations extension method for adding decorations to the ProseMirror EditorView.
  • New lifecycle methods: onInitState, onApplyState, and onApplyTransaction lifecycle methods. These correspond exactly the the plugin methods which ProseMirror exposes and can be used to create plugin functionality without creating a new plugin.
  • @command, @keyBinding, @helper decorators for increased type safety when configuring extensions.
  • NamedShortcut keybindings which can be set on the keymap extension. Currently remirror defaults to using the same shortcuts as Google Docs.
  • Add the nodeOverrides property to the extensions which for advanced users allows overriding of the default NodeSpec and MarkSpec.
  • Rename addOrReplacePlugins to updatePlugins in ExtensionStore.
  • Remove reconfigureStatePlugins and auto apply it for all plugin updating methods.

Inference of Extension Types

  • Make sure all your commands in an extension are annotated with a return type of CommandFunction. Failure to do so will break all type inference wherever the extension is used.

    import { CommandFunction } from 'remirror';
    
  • When setting the name of the extension make sure to use as const otherwise it will be a string and ruin autocompletion for extension names, nodes and marks.

    class MyExtension extends PlainExtension {
      get name() {
        return 'makeItConst' as const;
      }
    }
    
  • The Remirror component now has a convenient hooks props. The hooks prop takes an array of zero parameter hook functions which are rendered into the RemirrorContext. It's a shorthand to writing out your own components. You can see the pattern in use above.

Commands

There are new hooks for working with commands.

  • Each command has an original method attached for using the original command that was used to create the command. The original command has the same type signature as the (...args: any[]) => CommandFunction. So you would call it with the command arguments and then also provide the CommandProps. This is useful when composing commands together or using commands within keyBindings which need to return a boolean.

    • You can see the insertText.original being used in the useKeymap example above.
  • useCommands() provides all the commands as hook. useChainedCommands provides all the chainable commands.

    import { useCallback } from 'react';
    import { useChainedCommands, useKeymap } from '@remirror/react';
    
    function useLetItGo() {
      const chain = useChainedCommands();
      const handler = useCallback(() => {
        chain.selectText('all').insertText('Let it goo 🤫').run();
      }, [chain]);
    
      // Whenever the user types `a` they let it all go
      useKeymap('a', handler);
    }
    

Dependencies

  • Upgrade React to require minimum versions of ^16.14.0 || ^17. This is because of the codebase now using the new jsx transform.
  • Upgrade TypeScript to a minimum of 4.3. Several of the new features make use of the new types and it is a requirement to upgrade.
  • General upgrades across all dependencies to using the latest versions.
    • All prosemirror-* packages.
remirror - v1.0.0-next.60

Published by ifiokjr almost 4 years ago

Breaking 💥

  • 4504aadb #830 Thanks @ifiokjr! - Rename deprecated error constant from COMMANDS_CALLED_IN_OUTER_SCOPE to SCHEMA.

Features ✨

  • 4504aadb #830 Thanks @ifiokjr! - Add getActiveNode function which returns the information for an active node of the provided type.

  • 4504aadb #830 Thanks @ifiokjr! - Add getMarkRanges which supports retrieving all the mark ranges from within the provided selection.

Fixes 🔧

  • 4504aadb #830 Thanks @ifiokjr! - Preserve attributes when toggling a block node. This allows for better support when using extraAttributes and fixes #819.

  • 302bdf7e #829 Thanks @benjie! - Fix regexp for image filetype check.

  • 34a7981d #828 Thanks @tommoor! - YJS fixes for scrolling while remote clients are editing and incorrect remote selections.

remirror - v1.0.0-next.59

Published by ifiokjr almost 4 years ago

Fixes 🔧

  • e69115f1 #825 Thanks @tommoor! - Fix getMarkRange not returning the entire mark length, instead stopping at the first change in mark. This fix also resolves the infinite loop described in #823.
remirror - v1.0.0-next.58

Published by ifiokjr almost 4 years ago

Fixes 🔧

  • 3d3da227 #815 Thanks @ifiokjr! - Allow access to extension.store.currentState before the first state update. This fixes #814.
remirror - v1.0.0-next.57

Published by ifiokjr almost 4 years ago

Fixes

  • 4ae3c9b2 #812 Thanks @whawker! - Fix rendered HTML when selecting or applying marks to part of a link.

    Behaviour before fix.

    <p>
      <a href="/">My partially</a>
      <a href="/"><span class="selection">selected</span></a>
      <a href="/">link</a>
    </p>
    

    Behaviour after fix.

    <p>
      <a href="/">
        My partially
        <span class="selection">selected</span>
        link
      </a>
    </p>
    
remirror - v1.0.0-next.56

Published by ifiokjr almost 4 years ago

This is (hopefully 🤞) the release before the beta release.

Fixes

remirror - v1.0.0-next.55

Published by ifiokjr almost 4 years ago

New Features

  • 1adea88a #801 Thanks @ifiokjr! - Add new primitive commands to CommandsExtension.

    • setBlockNodeType
    • toggleWrappingNode
    • toggleBlockNodeItem
    • wrapInNode
    • removeMark
  • ee1ab4f3 #805 Thanks @ifiokjr! - Add GetMarkRange interface to exports from @remirror/core-utils.

  • 1adea88a #801 Thanks @ifiokjr! - Improve type signatures of command utility functions to also include an optional range.

  • 4bdcac77 #805 Thanks @ifiokjr! - Add click and clickMark handlers to the EventsExtension. These new events are available to hooks created with useExtension(EventsExtension) and also exposed via the new createEventHandlers extension method. These methods provides utilities for determining whether the position clicked was within a specific node or mark.

  • b65ea785 #805 Thanks @ifiokjr! - Add onClick handler to LinkExtension which is called with the event: MouseEvent and data: LinkClickData which includes the href and all the GetMarkRange properties.

    Export extra types from the @remirror/extension-link package.

    • LinkAttributes
    • LinkClickData
    • DefaultProtocol
  • 3ee20d40 #805 Thanks @ifiokjr! - Add onClick handler to MentionExtension which is called with event: MouseEvent and markRange: GetMarkRange.

  • c2268721 #805 Thanks @ifiokjr! - Add onClick handler to MentionAtomExtension which is called with the event: MouseEvent and nodeWithPosition: NodeWithPosition.

Fixes

  • 1adea88a #801 Thanks @ifiokjr! - Fix getChangedNodeRanges when resolving content that may no longer be within the range of the full document. This addresses the issues raised in #797 and #764.
remirror - v1.0.0-next.54

Published by ifiokjr almost 4 years ago

Features

  • b1df359b #780 Thanks @ocavue! - Add new@remirror/extension-codemirror5 package which can be used as an alternative to the @remirror/extension-codeblock for representing code blocks with syntax highlighting in your editor.

  • d720bcd4 #791 Thanks @ifiokjr! - Rename codemirror package to include the version number: @remirror/extension-codemirror5. This is to allow a future seperate version which supports codemirror@6.

    Make codemirror and @types/codemirror peer dependencies of the @remirror/extension-codemirror5 package. Most setups will need to install codemirror in order to add language support to the code editor. To avoid bundling multiple versions of the same codebase a peer dependency architecture seems to work.

Minor Changes

  • e9d95fa4 #786 Thanks @ifiokjr! - Export PrioritizedKeyBindings from @remirror/core and remirror/core entry points.

  • 1b5bf359 #788 Thanks @ifiokjr! - Make draggability configurable for MentionAtomExtension as mentioned in #777.

Fixes

  • 8a6d5c34 #781 Thanks @whawker! - The behaviour of commands.updateLink.isEnabled() has been fixed to return false when the link mark can't be applied to the selection. This was fixed by a change in the @remirror/core-utils package.

  • e9d95fa4 #786 Thanks @ifiokjr! - Fix problems around destroying the YjsExtension provider and the CMD+SHIFT+Z keymap not registering as mentioned in #772.

  • 1a0348e7 #789 Thanks @ifiokjr! - Fix removeMark when called with dispatch = undefined. This means that command.<NAME>.isEnabled() checks should all be fixed if they are using removeMark as mentioned in #784.

remirror - v1.0.0-next.53

Published by ifiokjr almost 4 years ago

Fixes

  • a1d65df6 #775 Thanks @whawker! - Fixes extensions that were erroneously adding extra attributes to the DOM twice.

    Attributes were correctly added using their toDOM handler, but also incorrectly in their raw form.

    Example

    const linkExtension = new LinkExtension({
      extraAttributes: {
        custom: {
          default: 'my default',
          parseDOM: (dom) => dom.getAttribute('data-custom'),
          toDOM: (attrs) => ['data-custom', attrs.custom],
        },
      },
    });
    

    Resulted in

    <a data-custom="my default" custom="my default" <!-- extra attribute rendered in raw form -->
      href="https://remirror.io" rel="noopener noreferrer nofollow"></a
    >
    
  • 5fd944c6 #770 Thanks @whawker! - Prevent callouts being merged when removing content in between callout nodes.

remirror - v1.0.0-next.52

Published by ifiokjr almost 4 years ago

Major Changes

  • bdaa6af7 #767 Thanks @whawker! - 🎉 New extension @remirror/extension-callout

    This extension adds support for a new callout node.

    These can be used to add info, warning, error or success banners to your document.

    The default callout type is info, but this can be changed by using the defaultType option of CalloutExtension.

    import { RemirrorManager } from 'remirror/core';
    import { CalloutExtension } from 'remirror/extension/callout';
    import { CorePreset } from 'remirror/preset/core';
    
    // Create the callout extension
    const calloutExtension = new CalloutExtension();
    const corePreset = new CorePreset();
    
    // Create the Editor Manager with the callout extension passed through.
    const manager = RemirrorManager.create([calloutExtension, corePreset]);
    
    // Pass the dom element to the editor. If you are using `@remirror/react` or
    // other framework wrappers then this is handled for you.
    const element = document.createElement('div');
    document.body.append(element);
    
    // Add the view to the editor manager.
    manager.addView(element);
    
    // Wrap with an error callout at the current selection
    manager.store.commands.toggleCallout({ type: 'error' });
    
  • caf2588d #766 Thanks @ronnyroeller! - Allow links to be clickable

    Anchor tags in contenteditable are not clickable by default. To allow users nonetheless to open them, this commit adds an optional clickhandler to open the link.

Patch Changes

  • 3da2b5fd Thanks @ifiokjr! - Fixes #768 error when addYouTubeVideo.isEnabled() is called.
remirror - v1.0.0-next.51

Published by ifiokjr almost 4 years ago

Major Changes

  • b79e4142 #761 Thanks @whawker! - BREAKING avoid using the paste rule if autoLink is enabled for LinkExtension
remirror - v1.0.0-next.50

Published by ifiokjr about 4 years ago

Minor Changes

  • d27c6e1a #758 Thanks @ifiokjr! - Pass through defaultAppendTextValue property to onChange handler of MentionExtension.
  • 359486f6 #754 Thanks @whawker! - Add an onUpdatedLink event handler to the link extension for determining when a link has been added to the document.
  • d27c6e1a #758 Thanks @ifiokjr! - Support EditorState | Selection | ResolvedPos for the findParentNodeOfType function.
    • d27c6e1a #758 Thanks @ifiokjr! - Don't append text to useMention hook command when content after starts with whitespace.

Patch Changes

remirror - v1.0.0-next.49

Published by ifiokjr about 4 years ago

Patch Changes

  • cd91b689 Thanks @ifiokjr! - Fix command for useEmoji when called asynchronously.

  • 049134a3 #749 Thanks @ifiokjr! - Add types for the virtualNode property on the useMultiPositioner and usePositioner hooks. Also improve performance with useLayoutEffect instead of useEffect.

remirror - v1.0.0-next.48

Published by ifiokjr about 4 years ago

Minor Changes

remirror - v1.0.0-next.47

Published by ifiokjr about 4 years ago

Major Changes

  • 56349ca5 #744 Thanks @ifiokjr! - Add new options to the YjsExtension to support full configuration of the y-prosemirror plugins.

    BREAKING: 💥 Remove WebrtcProvider. It was always required via TypeScript but now the default implementation throws an error if you don't install and provide the provider you want to use. The readme has been updated to reflect this change.

    BREAKING: 💥 yjs is now a peerDependency and you will need to install it in your codebase to consume the YjsExtension. This change follows from the above breaking change. For example, to configure any provider will need to provide your desired Doc from the yjs package.

Minor Changes

Patch Changes

remirror - v1.0.0-next.46

Published by ifiokjr about 4 years ago

Minor Changes

  • 73e81b43 #739 Thanks @ronnyroeller! - Configure blockseparator to concat multi-block content

    getAnnotations() return all currently set annotations and enriches them with the text of the annotation. This can be used e.g. to show a list of all annotations outside the editor context. Before, text from multiple blocks (in a multi-block annotation) was concatenated without any separated. Now, one can define via the "blockseparator" option which string to use as separator. For example, one could use a newline character to separate text from different blocks.

  • 0198b9fc #740 Thanks @whawker! - Add strike mark to the jest-prosemirror schema

remirror - v1.0.0-next.45

Published by ifiokjr about 4 years ago

Patch Changes

  • 2175be1d Thanks @ifiokjr! - Fix CommandExtension error when editor started without an attached framework.
Package Rankings
Top 1.07% on Npmjs.org
Related Projects