Skip to content

Conversation

@mdmower
Copy link
Contributor

@mdmower mdmower commented May 26, 2024

Description

  • Introduce code format button component in react-ui (heavily inspired by the language-select component) that makes a floating "Format" button available for the code block extension.
    • Changelog includes examples of how to use the component, including how to supply a formatter for the feature.
  • Replace storybook entry CodeBlock: WithLanguageSelect with CodeBlock: WithTools that includes both language select and format tools.
  • Fix JS/TS entry for all CodeBlock samples (missing function parentheses).

Checklist

  • I have read the contributing document.
  • My code follows the code style of this project and pnpm fix completed successfully.
  • I have updated the documentation where necessary.
  • New code is unit tested and all current tests pass when running pnpm test.

Screenshots

Initial view of CodeBlock: WithTools

image

Final view after all code blocks have been formatted:

image

@changeset-bot
Copy link

changeset-bot bot commented May 26, 2024

🦋 Changeset detected

Latest commit: 2105ecc

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 5 packages
Name Type
@remirror/extension-code-block Patch
@remirror/react-ui Patch
remirror Patch
@remirror/preset-wysiwyg Patch
@remirror/react-editors Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@mdmower mdmower mentioned this pull request May 26, 2024
4 tasks
@whawker
Copy link
Collaborator

whawker commented Jul 20, 2024

Thanks for the contribution @mdmower! Sorry it's taken so long to get back to you, life has been hectic recently.

With the upcoming Remirror v3 the @remirror/extension-react-language-select has been removed, in favour of a component in the new @remirror/react-ui package.

See here

Would you be interested in reworking this extension as as component instead, and opening a PR against the v3 branch?

@mdmower
Copy link
Contributor Author

mdmower commented Jul 20, 2024

Would you be interested in reworking this extension as as component instead, and opening a PR against the v3 branch?

@whawker - thanks for taking a look! Most of my motivation for this PR stems from #2255 so that my project can update prettier to v3 (see issue #2250). After working on that PR, I wanted to make sure there was an easy way to demonstrate the formatter works correctly... hence this PR. Before I dive into rebasing and reworking this PR, could you let me know whether a PR like #2255 would be considered for v3? I'm not sure how you all feel about an async code formatter since it deviates from most other chainable formatters.

EDIT: I've gone ahead and rebased both PRs on top of branch v3.

@mdmower mdmower changed the base branch from main to v3 July 21, 2024 22:29
@mdmower mdmower changed the title feat: Add React code block formatter extension @remirror/extension-react-format-code and create storybook entry feat: Add code block formatter to react-ui Jul 21, 2024
@mdmower mdmower changed the title feat: Add code block formatter to react-ui feat: add code block formatter to react-ui Jul 22, 2024
@whawker
Copy link
Collaborator

whawker commented Jul 24, 2024

Hi @mdmower, would you mind rebasing this on v3?

@mdmower mdmower marked this pull request as ready for review July 24, 2024 13:37
@mdmower
Copy link
Contributor Author

mdmower commented Jul 24, 2024

Is manual positioning sufficient for the case where both language-select and format are desired?

<Remirror manager={manager} initialContent={state} autoRender>
  <CodeBlockFormatCode />
  <CodeBlockLanguageSelect offset={{ x: -75, y: 0 }} />
</Remirror>

Or should they auto position relative to each other when both are included?

@whawker
Copy link
Collaborator

whawker commented Jul 24, 2024

Good point, there should probably be a parent "menu" component that is responsible for positioning with the code block, then you pass the functional buttons as children.

@mdmower
Copy link
Contributor Author

mdmower commented Jul 24, 2024

Good point, there should probably be a parent "menu" component that is responsible for positioning with the code block, then you pass the functional buttons as children.

@whawker - I refactored the language select and format button components into a new CodeBlockTools component in dcbbe11. It's a breaking change to the already breaking change where language select was moved to react-ui, but this seemed ok since v3 is still in beta. The storybook has been updated as well:
image

Let me know if you're on board with this change; it can be reverted if not. Usage of CodeBlockTools looks like:

<CodeBlockTools
  enableFormatButton={true/undefined}
  formatButtonOptions={{...}}
  enableLanguageSelect={true/undefined}
  languageSelectOptions={{...}}
/>

mdmower and others added 2 commits July 25, 2024 09:25
Introduce CodeBlockTools component in react-ui that houses both the
language select component and the format code button. Let the two
features be enabled independently or at the same time.
@whawker
Copy link
Collaborator

whawker commented Jul 25, 2024

@mdmower I took the liberty of cleaning up the commit history to get rid of all the merges (I know this will be squashed on merge, but it helps me when I come back later)

I have modified the CodeBlockTools to use composition, rather than enable props - just to make things more flexible around which was round you want the buttons to be etc.

Have a look and let me know what you think.

Example usage:

<CodeBlockTools>
  <CodeBlockLanguageSelect />
  <CodeBlockFormatButton />
</CodeBlockTools>

@whawker whawker merged commit 5c686c3 into remirror:v3 Jul 25, 2024
Copy link
Contributor Author

@mdmower mdmower left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have modified the CodeBlockTools to use composition, rather than enable props - just to make things more flexible around which was round you want the buttons to be etc.

Have a look and let me know what you think.

That's great, thanks @whawker! These were long PRs to review; thanks for all your time.

A few questions for my edification are below.

Comment on lines +25 to +28
const handleClick = (e: MouseEvent<HTMLButtonElement>) => {
if (onClick?.(e)) {
return;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I copied this early return from the language select component but I meant to ask about it. Is this an established convention in the project that if a user supplies their own event handler, they should return true to prevent remirror's default handling?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm I missed this. No to my knowledge it's not a convention in the code base. Tempted to drop the return here as it'll be much harder to make such changes later

Copy link
Contributor Author

@mdmower mdmower Jul 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if the intention was to make this behave like the onclick= attribute in HTML elements where returning false prevents the default handler (but does not stop propagation)?

if (onClick?.(e) === false) {
  return;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Erm... I suppose I should be referencing language select code rather than speculating on intention of my own code.

const handleChange = (e: SelectChangeEvent) => {
if (onSelectChange?.(e)) {
return;
}

Perhaps the intention there was

const handleChange = (e: SelectChangeEvent) => {
  if (onSelectChange?.(e) === false) {
    return;
  }

Comment on lines 3639 to +3644
'@storybook/builder-vite':
specifier: ^7.0.18
version: 7.0.18(typescript@5.5.3)(vite@4.3.9)
version: 7.0.18(typescript@5.0.4)(vite@4.3.9)
'@storybook/builder-webpack5':
specifier: ^7.0.18
version: 7.0.18(@swc/core@1.3.76)(esbuild@0.17.19)(react-dom@18.2.0)(react@18.2.0)(typescript@5.5.3)
version: 7.0.18(@swc/core@1.3.76)(esbuild@0.17.19)(react-dom@18.2.0)(react@18.2.0)(typescript@5.0.4)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't used pnpm outside of this project and was wary of the huge numbers of changes that occur in pnpm-lock.yaml which seem unrelated to my package updates. Is this just expected churn that I shouldn't worry about in the future?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect all that is need is to run pnpm dedupe. I can do that once V3 in merged to main

"@mui/material": "^5.13.2",
"@remirror/core": "3.0.0-beta.8",
"@remirror/dev": "3.0.0-beta.8",
"@remirror/extension-code-block": "^3.0.0-beta.8",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't sure whether beta.8 or beta.9 should be used here. Released version beta.8 does not have the necessary changes to support this feature. beta.9 doesn't exist. I understand it doesn't matter for local development, but when planning for future releases, is the strategy to include the most recent released package from this monorepo and know that upon next release this version will get bumped?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just install the current version and then run pnpm refresh, that sorts out all the links locally.

Then when merging the PR, the changeset file ensure everything gets bumped to the latest version before NPM publish

whawker added a commit that referenced this pull request Jul 30, 2024
* feat(core): decouple Lingui from core, move into optional `@remirror/i18n` (#2128)

* fix(react-components): remove unnecessary dependency from @remirror/react-components

* BREAKING: decouple Lingui from core, move into optional @remirror/i18n

* feat(messages): extract the messages into JSON files

* docs(storybook): add examples using different i18n libraries

* fix: try to resolve isExternal error

* fix: remove @lingui/core from @remirror/messages

* fix: remove @remirror/i18n from @remirror/react-core

* test(react-core): ensure the i18nFormat function is provided by hook

* fix: revert lingui extract to be done from the root folder

* docs(core-types): add descriptions for the new types

* chore: update changeset

* feat: use stage-3 ES decorator (#2166)

* chore: run pnpm fix

* chore: enter v3 beta release

* chore: fix cyclic dependency (#2168)

* chore: skip storybook-react when building packages

* chore(ci): enable turbo remote cache (#2171)

* chore: clean changeset

* chore: update .eslintignore

* chore(changeset): version update (beta) (#2170)

* chore(ci): try to fix ci test

* chore: cache more output files

* chore: build jest-prosemirror

* chore: increase size-limit

* chore: run pnpm dedupe

* chore: build testing

* chore: fix test

* chore(ci): increase timeout-minutes

* chore: run pnpm fix

* chore: fix publish-v3 name

* chore: set publish branch to v3

* chore: fix the build script for @remirror/messages and @remirror/theme

* chore: fix the build script for @remirror/react

* chore: add script `build:packages:force`

* fix(pm): update ProseMirror dependencies to latest versions (#2192)

* feat(mention-atom): add leaf text for mention atom nodes (#2190)

* chore: fix `watch:skip-build` script

* feat: extract MUI react components into `@remirror/react-ui` (#2193)

* feat: extract MUI react components into a new optional package `@remirror/react-ui`

* docs: add custom mui theme example

* feat: make `extension` decorator backwards compatible when called as function (#2191)

* chore(core): remove deprecated extensionDecorator

* fix(core): make extension decorator backward compatible (when called as function)

* docs: tidy up (#2196)

* docs: remove beta notice from file extension

* fix: remove incorrect usage statement from `@remirror/react-ui` readme

* docs: add orphaned extension docs to the index page

* chore(changeset): version update (beta) (#2194)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* chore: downgrade build target (#2197)

* chore: downgrade build target

* chore(changeset): version update (beta) (#2198)

* chore: downgrade build target to support browsers since 2017 (#2199)

* chore: downgrade build target to support browsers since 2017

* fix: increase size limit on some packages

* chore(changeset): version update (beta) (#2200)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* fix: bump all packages to rebuild for browsers since 2017 (#2201)

* chore(changeset): version update (beta) (#2202)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* chore: remove deprecated items (#2208)

* chore(theme): remove deprecated functions

* chore(types): remove deprecated types

* chore(jest-remirror): remove deprecated start and end values

* chore(jest-prosemirror): remove deprecated jumpTo function

* chore(core-constants): remove deprecated error code

* chore(core): remove deprecated `getRemirrorJSON` helper

* chore: remove deprecated `isEnabled` command helper

* chore(events): remove deprecated types

* chore(react-hooks): remove deprecated useSuggester alias

* fix: reorganise changeset severity

* fix(react-ui): language selector should be a component, not an extension (#2203)

* fix(react-ui): language selector should be a component, not an extension

* feat(find): remove deprecated `SearchExtension`, add `FindButton` component (#2213)

* feat(preset-wysiwyg): remove deprecated search extension, replace with find extension

* feat(react-ui): add find button and ability to toggle replace

* chore(changeset): version update (beta) (#2210)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* Merge remote-tracking branch 'origin/main' into v3

* fix: bump to an version of esbuild that supports decorators

* chore: add changeset

* chore: bump all packages for next beta

* fix: audit errors

* fix: actually fix audit error

* fix: run pnpm fix

* fix: support older environments

* fix: override typescript version used in build

* chore: add satisfies to custom extension docs

* fix: update formatjs version to trigger typescript change

* chore: try to specific typescript version in cli

* fix: output type definitions correctly

* chore(changeset): version update (beta) (#2271)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* chore: forward-port validate property removal

* chore(changeset): version update (beta) (#2274)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* chore: remove React Tables extension from `@remirror/react`

* chore: remove YjsExtension from `remirror/extensions`

* chore: remove CodemirrorExtension from `remirror/extensions`

* fix: missing tsconfig reference

* chore: export cx from core-helpers using clsx

* fix: actually fix tsconfig for markdown ext

* chore(changeset): version update (beta) (#2276)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* feat: upgrade to prettier v3.2 (#2255)

* feat: Upgrade to prettier v3.2

* (Revisions) feat: Upgrade to prettier v3.2

- Extract code language string to parser name identification into its
  own function.

* (Revisions) feat: Upgrade to prettier v3.2

- Use DelayedCommand to generate command formatCodeBlock and make the
  command generator available via the extension store.
- Refactor formatCodeBlockFactory into formatCode that only returns
  information about document updates to be applied instead of also
  dispatching transactions itself.

* (Revisions) feat: Upgrade to prettier v3.2

- Revisions from review

* fix: formatCodeBlock cannot be chained

* test: use exposed formatter in unit tests

* chore: update changeset

* test: use a more realistic custom formatter

---------

Co-authored-by: William Hawker <w.hawker@hotmail.co.uk>

* fix: update loglevel arg in helper script (#2278)

* feat: add code block formatter to react-ui (#2256)

* feat: add code formatter button extension

* feat: add button for code block formatting 

Introduce CodeBlockTools component in react-ui that positions components
with a code block

Introduce a CodeBlockFormatButton component that formats code blocks
using the provided formatter

---------

Co-authored-by: William Hawker <w.hawker@hotmail.co.uk>

* chore: switch to release candidate builds

* chore(changeset): version update (rc) (#2277)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* fix: do not exit formatting if `onClick` provided

* chore: update styled-components to v6 (#2280)

* chore: update styled-components to v6

- styled-components is a peer dependency, so other projects rely on
  remirror keeping it up to date or they can be blocked from updating it
  themselves (without overrides); bump to v6.
- Remove @types/styled-components since types are bundled with v6.

Fixes #2279

* fix: remove incorrect type declarations from styles

While typing exported variables is generally good practice, the types
applied to style constants were nothing more than an attempt to derive
the return type of the function being called, and they were incorrect.
Assign the values and let the type inference do its magic.

Fix the order of imports in styled-components.tsx so that when the file
is regenerated its imports agree with lint rules.

---------

Co-authored-by: William Hawker <w.hawker@hotmail.co.uk>

* chore: exit pre-release mode

* chore: remove references to obsolete extensions

---------

Co-authored-by: ocavue <ocavue@gmail.com>
Co-authored-by: William Hawker <w.hawker@hotmail.co.uk>
Co-authored-by: Matt Mower <mdmower@cmphys.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants