Skip to content

Commit 34043b7

Browse files
committed
fix(TextDirection): Adjust to our code style
Signed-off-by: Jonas <[email protected]>
1 parent bf8ff09 commit 34043b7

File tree

1 file changed

+160
-142
lines changed

1 file changed

+160
-142
lines changed

src/extensions/TextDirection.ts

Lines changed: 160 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -1,157 +1,175 @@
1-
import { Extension } from "@tiptap/core";
2-
import { Plugin, PluginKey } from "@tiptap/pm/state";
1+
/**
2+
* SPDX-FileCopyrightText: 2023 Amir Hossein Hashemi
3+
* SPDX-License-Identifier: MIT
4+
*/
35

4-
const RTL = "\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC";
6+
import { Extension } from '@tiptap/core'
7+
import { Plugin, PluginKey } from '@tiptap/pm/state'
8+
9+
const RTL = '\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC'
510
const LTR =
6-
"A-Za-z\u00C0-\u00D6\u00D8-\u00F6" +
7-
"\u00F8-\u02B8\u0300-\u0590\u0800-\u1FFF\u200E\u2C00-\uFB1C" +
8-
"\uFE00-\uFE6F\uFEFD-\uFFFF";
9-
10-
const RTL_REGEX = new RegExp("^[^" + LTR + "]*[" + RTL + "]");
11-
const LTR_REGEX = new RegExp("^[^" + RTL + "]*[" + LTR + "]");
12-
13-
// Source: https://github.com/facebook/lexical/blob/429e3eb5b5a244026fa4776650aabe3c8e17536b/packages/lexical/src/LexicalUtils.ts#L163
14-
export function getTextDirection(text: string): "ltr" | "rtl" | null {
15-
if (text.length == 0) {
16-
return null;
17-
}
18-
if (RTL_REGEX.test(text)) {
19-
return "rtl";
20-
}
21-
if (LTR_REGEX.test(text)) {
22-
return "ltr";
23-
}
24-
return null;
11+
'A-Za-z\u00C0-\u00D6\u00D8-\u00F6'
12+
+ '\u00F8-\u02B8\u0300-\u0590\u0800-\u1FFF\u200E\u2C00-\uFB1C'
13+
+ '\uFE00-\uFE6F\uFEFD-\uFFFF'
14+
15+
/* eslint-disable no-misleading-character-class */
16+
const RTL_REGEX = new RegExp('^[^' + LTR + ']*[' + RTL + ']')
17+
const LTR_REGEX = new RegExp('^[^' + RTL + ']*[' + LTR + ']')
18+
19+
/**
20+
* @param text Text string
21+
*
22+
*Source: https://github.com/facebook/lexical/blob/429e3eb5b5a244026fa4776650aabe3c8e17536b/packages/lexical/src/LexicalUtils.ts#L163
23+
*/
24+
export function getTextDirection(text: string): 'ltr' | 'rtl' | null {
25+
if (text.length === 0) {
26+
return null
27+
}
28+
if (RTL_REGEX.test(text)) {
29+
return 'rtl'
30+
}
31+
if (LTR_REGEX.test(text)) {
32+
return 'ltr'
33+
}
34+
return null
2535
}
2636

27-
const validDirections = ["ltr", "rtl", "auto"] as const;
37+
const validDirections = ['ltr', 'rtl', 'auto'] as const
2838

29-
type Direction = (typeof validDirections)[number];
39+
type Direction = (typeof validDirections)[number]
3040

41+
/**
42+
* @param object Property object
43+
* @param object.types List of node types to consider
44+
*/
3145
function TextDirectionPlugin({ types }: { types: string[] }) {
32-
return new Plugin({
33-
key: new PluginKey("textDirection"),
34-
appendTransaction: (transactions, oldState, newState) => {
35-
const docChanges = transactions.some(
36-
(transaction) => transaction.docChanged,
37-
);
38-
if (!docChanges) {
39-
return;
40-
}
41-
42-
let modified = false;
43-
const tr = newState.tr;
44-
tr.setMeta("addToHistory", false);
45-
46-
newState.doc.descendants((node, pos) => {
47-
if (types.includes(node.type.name)) {
48-
if (node.attrs.dir !== null && node.textContent.length > 0) {
49-
return;
50-
}
51-
const marks = tr.storedMarks || [];
52-
tr.setNodeAttribute(pos, "dir", getTextDirection(node.textContent));
53-
// `tr.setNodeAttribute` resets the stored marks so we'll restore them
54-
for (const mark of marks) {
55-
tr.addStoredMark(mark);
56-
}
57-
modified = true;
58-
}
59-
});
60-
61-
return modified ? tr : null;
62-
},
63-
});
46+
return new Plugin({
47+
key: new PluginKey('textDirection'),
48+
appendTransaction: (transactions, oldState, newState) => {
49+
const docChanges = transactions.some(
50+
(transaction) => transaction.docChanged,
51+
)
52+
if (!docChanges) {
53+
return
54+
}
55+
56+
let modified = false
57+
const tr = newState.tr
58+
tr.setMeta('addToHistory', false)
59+
60+
newState.doc.descendants((node, pos) => {
61+
if (types.includes(node.type.name)) {
62+
if (node.attrs.dir !== null && node.textContent.length > 0) {
63+
return
64+
}
65+
const marks = tr.storedMarks || []
66+
tr.setNodeAttribute(
67+
pos,
68+
'dir',
69+
getTextDirection(node.textContent),
70+
)
71+
// `tr.setNodeAttribute` resets the stored marks so we'll restore them
72+
for (const mark of marks) {
73+
tr.addStoredMark(mark)
74+
}
75+
modified = true
76+
}
77+
})
78+
79+
return modified ? tr : null
80+
},
81+
})
6482
}
6583

66-
declare module "@tiptap/core" {
67-
interface Commands<ReturnType> {
68-
textDirection: {
69-
/**
70-
* Set the text direction attribute
71-
*/
72-
setTextDirection: (direction: Direction) => ReturnType;
73-
/**
74-
* Unset the text direction attribute
75-
*/
76-
unsetTextDirection: () => ReturnType;
77-
};
78-
}
84+
declare module '@tiptap/core' {
85+
interface Commands<ReturnType> {
86+
textDirection: {
87+
/**
88+
* Set the text direction attribute
89+
*/
90+
setTextDirection: (direction: Direction) => ReturnType
91+
/**
92+
* Unset the text direction attribute
93+
*/
94+
unsetTextDirection: () => ReturnType
95+
}
96+
}
7997
}
8098

8199
export interface TextDirectionOptions {
82-
types: string[];
83-
defaultDirection: Direction | null;
100+
types: string[]
101+
defaultDirection: Direction | null
84102
}
85103

86104
export const TextDirection = Extension.create<TextDirectionOptions>({
87-
name: "textDirection",
88-
89-
addOptions() {
90-
return {
91-
types: [],
92-
defaultDirection: null,
93-
};
94-
},
95-
96-
addGlobalAttributes() {
97-
return [
98-
{
99-
types: this.options.types,
100-
attributes: {
101-
dir: {
102-
default: null,
103-
parseHTML: (element) =>
104-
element.dir || this.options.defaultDirection,
105-
renderHTML: (attributes) => {
106-
if (attributes.dir === this.options.defaultDirection) {
107-
return {};
108-
}
109-
return { dir: attributes.dir };
110-
},
111-
},
112-
},
113-
},
114-
];
115-
},
116-
117-
addCommands() {
118-
return {
119-
setTextDirection:
120-
(direction: Direction) =>
121-
({ commands }) => {
122-
if (!validDirections.includes(direction)) {
123-
return false;
124-
}
125-
126-
return this.options.types.every((type) =>
127-
commands.updateAttributes(type, { dir: direction }),
128-
);
129-
},
130-
131-
unsetTextDirection:
132-
() =>
133-
({ commands }) => {
134-
return this.options.types.every((type) =>
135-
commands.resetAttributes(type, "dir"),
136-
);
137-
},
138-
};
139-
},
140-
141-
addKeyboardShortcuts() {
142-
return {
143-
"Mod-Alt-l": () => this.editor.commands.setTextDirection("ltr"),
144-
"Mod-Alt-r": () => this.editor.commands.setTextDirection("rtl"),
145-
};
146-
},
147-
148-
addProseMirrorPlugins() {
149-
return [
150-
TextDirectionPlugin({
151-
types: this.options.types,
152-
}),
153-
];
154-
},
155-
});
156-
157-
export default TextDirection;
105+
name: 'textDirection',
106+
107+
addOptions() {
108+
return {
109+
types: [],
110+
defaultDirection: null,
111+
}
112+
},
113+
114+
addGlobalAttributes() {
115+
return [
116+
{
117+
types: this.options.types,
118+
attributes: {
119+
dir: {
120+
default: null,
121+
parseHTML: (element) =>
122+
element.dir || this.options.defaultDirection,
123+
renderHTML: (attributes) => {
124+
if (attributes.dir === this.options.defaultDirection) {
125+
return {}
126+
}
127+
return { dir: attributes.dir }
128+
},
129+
},
130+
},
131+
},
132+
]
133+
},
134+
135+
addCommands() {
136+
return {
137+
setTextDirection:
138+
(direction: Direction) =>
139+
({ commands }) => {
140+
if (!validDirections.includes(direction)) {
141+
return false
142+
}
143+
144+
return this.options.types.every((type) =>
145+
commands.updateAttributes(type, { dir: direction }),
146+
)
147+
},
148+
149+
unsetTextDirection:
150+
() =>
151+
({ commands }) => {
152+
return this.options.types.every((type) =>
153+
commands.resetAttributes(type, 'dir'),
154+
)
155+
},
156+
}
157+
},
158+
159+
addKeyboardShortcuts() {
160+
return {
161+
'Mod-Alt-l': () => this.editor.commands.setTextDirection('ltr'),
162+
'Mod-Alt-r': () => this.editor.commands.setTextDirection('rtl'),
163+
}
164+
},
165+
166+
addProseMirrorPlugins() {
167+
return [
168+
TextDirectionPlugin({
169+
types: this.options.types,
170+
}),
171+
]
172+
},
173+
})
174+
175+
export default TextDirection

0 commit comments

Comments
 (0)