Skip to content

Commit

Permalink
fix(deps)!: update unified ecosystem dependencies
Browse files Browse the repository at this point in the history
BREAKING CHANGE: The minimum supported version for various peer dependencies have been upgraded.
  • Loading branch information
rfgamaral committed Aug 16, 2023
1 parent 185e904 commit 67a1310
Show file tree
Hide file tree
Showing 10 changed files with 1,828 additions and 244 deletions.
4 changes: 2 additions & 2 deletions .github/renovate.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
"groupName": "tiptap packages"
},
{
"matchPackagePatterns": ["gfm-autolink-literal"],
"matchPackagePatterns": ["gfm-autolink-literal$"],
"groupName": "gfm autolink literal packages"
},
{
"matchPackagePatterns": ["gfm-strikethrough"],
"matchPackagePatterns": ["gfm-strikethrough$"],
"groupName": "gfm strikethrough packages"
}
]
Expand Down
8 changes: 8 additions & 0 deletions .storybook/preview.style.css
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,11 @@ body,
#storybook-docs .sbdocs.sbdocs-wrapper {
padding: 3rem;
}

/*
* This is required becase `github-markdown-css` is a dev dependency (not necessarily used by
* consumers) which hides what the `rehypeCodeBlock` extension does.
*/
.markdown-body code br {
display: unset !important;
}
1,951 changes: 1,746 additions & 205 deletions package-lock.json

Large diffs are not rendered by default.

9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,13 @@
"@testing-library/dom": "9.3.1",
"@testing-library/jest-dom": "6.0.0",
"@testing-library/react": "14.0.0",
"@types/hast": "3.0.0",
"@types/lodash-es": "4.17.8",
"@types/react": "18.2.20",
"@types/react-dom": "18.2.7",
"@types/react-syntax-highlighter": "15.5.7",
"@types/turndown": "5.0.1",
"@types/unist": "3.0.0",
"@vitejs/plugin-react": "4.0.4",
"boring-avatars": "1.10.1",
"classnames": "2.3.2",
Expand Down Expand Up @@ -138,7 +140,6 @@
"peerDependencies": {
"@react-hookz/web": "^14.2.3 || >=15.x",
"emoji-regex": "^10.2.1",
"hast-util-is-element": "^2.1.0",
"lodash-es": "^4.17.21",
"mdast-util-gfm-autolink-literal": "^2.0.0",
"mdast-util-gfm-strikethrough": "^2.0.0",
Expand All @@ -155,9 +156,9 @@
"remark-gfm": "^3.0.0",
"remark-rehype": "^10.1.0",
"turndown": "^7.1.0",
"unified": "^10.1.0",
"unist-util-is": "^5.2.0",
"unified": "^11.0.0",
"unist-util-is": "^6.0.0",
"unist-util-remove": "^4.0.0",
"unist-util-visit": "^4.1.0"
"unist-util-visit": "^5.0.0"
}
}
28 changes: 24 additions & 4 deletions src/helpers/unified.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,33 @@
import { isTextNode } from './unified'
import { isHastElement, isHastTextNode } from './unified'

describe('Helper: Unified', () => {
describe('#isTextNode', () => {
describe('#isHastElement', () => {
test('returns `true` when the given node is an element with the specified tag name', () => {
expect(
// @ts-expect-error Simplified node for testing purposes
isHastElement({ type: 'element', tagName: 'div' }, 'div'),
).toBe(true)
})

test('returns `false` when the given node is NOT an element with the specified tag name', () => {
expect(
// @ts-expect-error Simplified node for testing purposes
isHastElement({ type: 'element', tagName: 'span' }, 'div'),
).toBe(false)
})

test('returns `false` when the given node is NOT an element', () => {
expect(isHastElement({ type: 'text' }, 'div')).toBe(false)
})
})

describe('#isHastTextNode', () => {
test('returns `true` when the given node is a hast text node', () => {
expect(isTextNode({ type: 'text' })).toBe(true)
expect(isHastTextNode({ type: 'text' })).toBe(true)
})

test('returns `false` when the given node is NOT a hast text node', () => {
expect(isTextNode({ type: 'element' })).toBe(false)
expect(isHastTextNode({ type: 'element' })).toBe(false)
})
})
})
23 changes: 18 additions & 5 deletions src/helpers/unified.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,29 @@
import { is } from 'unist-util-is'

import type { Node, Text } from 'hast'
import type { Element, Text } from 'hast'
import type { Node } from 'unist'

/**
* Check if a given node is a unist text node.
* Determines whether a given node is an hast element with a specific tag name.
*
* @param node The node to check.
* @param tagName The tag name to check for.
*
* @returns `true` if the node is a unist text node, `false` otherwise.
* @returns `true` if the node is an hast element with the specified tag name, `false` otherwise.
*/
function isTextNode(node: Node): node is Text {
function isHastElement(node: Node, tagName: Element['tagName']): node is Element {
return is(node, { type: 'element', tagName })
}

/**
* Determines whether a given node is hast a text node.
*
* @param node The node to check.
*
* @returns `true` if the node is a hast text node, `false` otherwise.
*/
function isHastTextNode(node: Node): node is Text {
return is(node, { type: 'text' })
}

export { isTextNode }
export { isHastElement, isHastTextNode }
11 changes: 5 additions & 6 deletions src/serializers/html/plugins/rehype-code-block.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { isElement } from 'hast-util-is-element'
import { visit } from 'unist-util-visit'

import { isTextNode } from '../../../helpers/unified'
import { isHastElement, isHastTextNode } from '../../../helpers/unified'

import type { Node } from 'hast'
import type { Transformer } from 'unified'
import type { Node } from 'unist'

/**
* A rehype plugin to remove the trailing newline from code blocks (i.e. the newline between the
Expand All @@ -16,9 +15,9 @@ function rehypeCodeBlock(): Transformer {
return (...[tree]: Parameters<Transformer>): ReturnType<Transformer> => {
visit(tree, 'element', (node: Node) => {
if (
isElement(node, 'pre') &&
isElement(node.children[0], 'code') &&
isTextNode(node.children[0].children[0])
isHastElement(node, 'pre') &&
isHastElement(node.children[0], 'code') &&
isHastTextNode(node.children[0].children[0])
) {
node.children[0].children[0].value = node.children[0].children[0].value.replace(
/\n$/,
Expand Down
11 changes: 6 additions & 5 deletions src/serializers/html/plugins/rehype-image.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { isElement } from 'hast-util-is-element'
import { remove } from 'unist-util-remove'
import { visit } from 'unist-util-visit'

import { isHastElement } from '../../../helpers/unified'

import type { Schema } from 'prosemirror-model'
import type { Transformer } from 'unified'
import type { Node, Parent } from 'unist'
Expand All @@ -17,21 +18,21 @@ function rehypeImage(schema: Schema): Transformer {

// Return the tree as-is if the editor does not support inline images
if (allowInlineImages) {
return (tree: Node) => tree
return (tree) => tree
}

return (...[tree]: Parameters<Transformer>): ReturnType<Transformer> => {
visit(tree, 'element', (node: Node, index: number, parent: Parent) => {
if (isElement(node, 'p')) {
const areAllChildrenImages = node.children.every((c) => isElement(c, 'img'))
if (isHastElement(node, 'p')) {
const areAllChildrenImages = node.children.every((c) => isHastElement(c, 'img'))

// Replace the paragraph with the image children if all children are images, or
// remove all images from the paragraph if it contains non-image children since the
// editor does not support inline images
if (areAllChildrenImages) {
parent.children.splice(index, 1, ...node.children)
} else {
remove(node, (n) => isElement(n, 'img'))
remove(node, (n) => isHastElement(n, 'img'))
}
}
})
Expand Down
14 changes: 8 additions & 6 deletions src/serializers/html/plugins/rehype-suggestions.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { isElement } from 'hast-util-is-element'
import { visit } from 'unist-util-visit'

import { buildSuggestionSchemaPartialRegex } from '../../../helpers/serializer'
import { isTextNode } from '../../../helpers/unified'
import { isHastElement, isHastTextNode } from '../../../helpers/unified'

import type { Node } from 'hast'
import type { Schema } from 'prosemirror-model'
import type { Transformer } from 'unified'
import type { Node } from 'unist'

/**
* A rehype plugin to add support for suggestions nodes (e.g., `@username` or `#channel).
Expand All @@ -18,19 +17,22 @@ function rehypeSuggestions(schema: Schema): Transformer {

// Return the tree as-is if the editor does not support suggestions
if (!suggestionSchemaPartialRegex) {
return (tree: Node) => tree
return (tree) => tree
}

return (...[tree]: Parameters<Transformer>): ReturnType<Transformer> => {
const suggestionSchemaRegex = new RegExp(`^${suggestionSchemaPartialRegex}`)

visit(tree, 'element', (node: Node) => {
if (isElement(node, 'a') && suggestionSchemaRegex.test(String(node.properties?.href))) {
if (
isHastElement(node, 'a') &&
suggestionSchemaRegex.test(String(node.properties?.href))
) {
const [, schema, id] =
/^([a-z-]+):\/\/(\S+)$/i.exec(String(node.properties?.href)) || []

// Replace the link element with a span containing the suggestion attributes
if (schema && id && isTextNode(node.children[0])) {
if (schema && id && isHastTextNode(node.children[0])) {
node.tagName = 'span'
node.properties = {
[`data-${schema}`]: '',
Expand Down
13 changes: 6 additions & 7 deletions src/serializers/html/plugins/rehype-task-list.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
import { isElement } from 'hast-util-is-element'
import { visit } from 'unist-util-visit'

import { isTextNode } from '../../../helpers/unified'
import { isHastElement, isHastTextNode } from '../../../helpers/unified'

import type { Node } from 'hast'
import type { Transformer } from 'unified'
import type { Node } from 'unist'

/**
* A rehype plugin to add support for Tiptap task lists (i.e., `* [ ] Task`).
*/
function rehypeTaskList(): Transformer {
return (...[tree]: Parameters<Transformer>): ReturnType<Transformer> => {
visit(tree, 'element', (node: Node) => {
if (isElement(node, 'ul')) {
if (isHastElement(node, 'ul')) {
const areAllChildrenTaskItems = node.children.every(
(c) =>
isElement(c, 'li') &&
isTextNode(c.children[0]) &&
isHastElement(c, 'li') &&
isHastTextNode(c.children[0]) &&
/^\[[ x]\] /i.test(c.children[0].value),
)

Expand All @@ -29,7 +28,7 @@ function rehypeTaskList(): Transformer {
}

node.children.forEach((c) => {
if (isElement(c, 'li') && isTextNode(c.children[0])) {
if (isHastElement(c, 'li') && isHastTextNode(c.children[0])) {
c.properties = {
...c.properties,
'data-type': 'taskItem',
Expand Down

0 comments on commit 67a1310

Please sign in to comment.