@portabletext/plugin-typography 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,246 @@
1
+ import type {EditorSchema} from '@portabletext/editor'
2
+ import {InputRule, InputRuleGuard} from '@portabletext/plugin-input-rule'
3
+ import {JSX} from 'react'
4
+
5
+ /**
6
+ * @public
7
+ */
8
+ export declare const closingDoubleQuoteRule: InputRule
9
+
10
+ /**
11
+ * @public
12
+ */
13
+ export declare const closingSingleQuoteRule: InputRule
14
+
15
+ /**
16
+ * @public
17
+ */
18
+ export declare const copyrightRule: InputRule
19
+
20
+ /**
21
+ * @public
22
+ * Create an `InputRuleGuard` that can prevent the rule from running inside
23
+ * certain decorators.
24
+ *
25
+ * @example
26
+ * ```tsx
27
+ * const guard = createDecoratorGuard({
28
+ * decorators: ({schema}) => schema.decorators.flatMap((decorator) => decorator.name === 'code' ? [decorator.name] : []),
29
+ * })
30
+ *
31
+ * <TypographyPlugin guard={guard} />
32
+ * ```
33
+ */
34
+ export declare function createDecoratorGuard(config: {
35
+ decorators: ({schema}: {schema: EditorSchema}) => Array<string>
36
+ }): InputRuleGuard
37
+
38
+ /**
39
+ * @public
40
+ */
41
+ export declare const ellipsisRule: InputRule
42
+
43
+ /**
44
+ * @public
45
+ */
46
+ export declare const emDashRule: InputRule
47
+
48
+ /**
49
+ * @public
50
+ */
51
+ export declare const laquoRule: InputRule
52
+
53
+ /**
54
+ * @public
55
+ */
56
+ export declare const leftArrowRule: InputRule
57
+
58
+ /**
59
+ * @public
60
+ */
61
+ export declare const multiplicationRule: InputRule
62
+
63
+ /**
64
+ * @public
65
+ */
66
+ export declare const notEqualRule: InputRule
67
+
68
+ /**
69
+ * @public
70
+ */
71
+ export declare const oneHalfRule: InputRule
72
+
73
+ /**
74
+ * @public
75
+ */
76
+ export declare const oneQuarterRule: InputRule
77
+
78
+ /**
79
+ * @public
80
+ */
81
+ export declare const openingDoubleQuoteRule: InputRule
82
+
83
+ /**
84
+ * @public
85
+ */
86
+ export declare const openingSingleQuoteRule: InputRule
87
+
88
+ /**
89
+ * @public
90
+ */
91
+ export declare const plusMinusRule: InputRule
92
+
93
+ /**
94
+ * @public
95
+ */
96
+ export declare const raquoRule: InputRule
97
+
98
+ /**
99
+ * @beta
100
+ */
101
+ export declare const registeredTrademarkRule: InputRule
102
+
103
+ /**
104
+ * @public
105
+ */
106
+ export declare const rightArrowRule: InputRule
107
+
108
+ /**
109
+ * @public
110
+ */
111
+ export declare const servicemarkRule: InputRule
112
+
113
+ /**
114
+ * @public
115
+ */
116
+ export declare const smartQuotesRules: Array<InputRule>
117
+
118
+ /**
119
+ * @public
120
+ */
121
+ export declare const superscriptThreeRule: InputRule
122
+
123
+ /**
124
+ * @public
125
+ */
126
+ export declare const superscriptTwoRule: InputRule
127
+
128
+ /**
129
+ * @public
130
+ */
131
+ export declare const threeQuartersRule: InputRule
132
+
133
+ /**
134
+ * @public
135
+ */
136
+ export declare const trademarkRule: InputRule
137
+
138
+ /**
139
+ * @public
140
+ */
141
+ export declare function TypographyPlugin(
142
+ props: TypographyPluginProps,
143
+ ): JSX.Element
144
+
145
+ /**
146
+ * @public
147
+ */
148
+ export declare type TypographyPluginProps = {
149
+ guard?: InputRuleGuard
150
+ /**
151
+ * Configure which rules to enable or disable. Ordinary rules like `emDash` and `ellipsis` are enabled by default.
152
+ * Less common rules like `multiplication` are disabled by default.
153
+ */
154
+ rules?: {
155
+ /**
156
+ * @defaultValue 'on'
157
+ */
158
+ emDash?: 'on' | 'off'
159
+ /**
160
+ * @defaultValue 'on'
161
+ */
162
+ ellipsis?: 'on' | 'off'
163
+ /**
164
+ * @defaultValue 'on'
165
+ */
166
+ openingDoubleQuote?: 'on' | 'off'
167
+ /**
168
+ * @defaultValue 'on'
169
+ */
170
+ closingDoubleQuote?: 'on' | 'off'
171
+ /**
172
+ * @defaultValue 'on'
173
+ */
174
+ openingSingleQuote?: 'on' | 'off'
175
+ /**
176
+ * @defaultValue 'on'
177
+ */
178
+ closingSingleQuote?: 'on' | 'off'
179
+ /**
180
+ * @defaultValue 'on'
181
+ */
182
+ leftArrow?: 'on' | 'off'
183
+ /**
184
+ * @defaultValue 'on'
185
+ */
186
+ rightArrow?: 'on' | 'off'
187
+ /**
188
+ * @defaultValue 'on'
189
+ */
190
+ copyright?: 'on' | 'off'
191
+ /**
192
+ * @defaultValue 'on'
193
+ */
194
+ trademark?: 'on' | 'off'
195
+ /**
196
+ * @defaultValue 'on'
197
+ */
198
+ servicemark?: 'on' | 'off'
199
+ /**
200
+ * @defaultValue 'on'
201
+ */
202
+ registeredTrademark?: 'on' | 'off'
203
+ /**
204
+ * @defaultValue 'off'
205
+ */
206
+ oneHalf?: 'on' | 'off'
207
+ /**
208
+ * @defaultValue 'off'
209
+ */
210
+ plusMinus?: 'on' | 'off'
211
+ /**
212
+ * @defaultValue 'off'
213
+ */
214
+ notEqual?: 'on' | 'off'
215
+ /**
216
+ * @defaultValue 'off'
217
+ */
218
+ laquo?: 'on' | 'off'
219
+ /**
220
+ * @defaultValue 'off'
221
+ */
222
+ raquo?: 'on' | 'off'
223
+ /**
224
+ * @defaultValue 'off'
225
+ */
226
+ multiplication?: 'on' | 'off'
227
+ /**
228
+ * @defaultValue 'off'
229
+ */
230
+ superscriptTwo?: 'on' | 'off'
231
+ /**
232
+ * @defaultValue 'off'
233
+ */
234
+ superscriptThree?: 'on' | 'off'
235
+ /**
236
+ * @defaultValue 'off'
237
+ */
238
+ oneQuarter?: 'on' | 'off'
239
+ /**
240
+ * @defaultValue 'off'
241
+ */
242
+ threeQuarters?: 'on' | 'off'
243
+ }
244
+ }
245
+
246
+ export {}
package/dist/index.js ADDED
@@ -0,0 +1,238 @@
1
+ import { getSelectedSpans, isActiveDecorator } from "@portabletext/editor/selectors";
2
+ import { defineTextTransformRule, InputRulePlugin } from "@portabletext/plugin-input-rule";
3
+ import { jsx } from "react/jsx-runtime";
4
+ import { c } from "react/compiler-runtime";
5
+ function createDecoratorGuard(config) {
6
+ return ({
7
+ snapshot,
8
+ event
9
+ }) => {
10
+ const decorators = config.decorators({
11
+ schema: snapshot.context.schema
12
+ });
13
+ if (decorators.length === 0)
14
+ return !0;
15
+ const matchedSpans = event.matches.flatMap((match) => getSelectedSpans({
16
+ ...snapshot,
17
+ context: {
18
+ ...snapshot.context,
19
+ selection: match.selection
20
+ }
21
+ }));
22
+ let preventInputRule = !1;
23
+ for (const decorator of decorators) {
24
+ if (isActiveDecorator(decorator)(snapshot)) {
25
+ preventInputRule = !0;
26
+ break;
27
+ }
28
+ if (matchedSpans.some((span) => span.node.marks?.includes(decorator))) {
29
+ preventInputRule = !0;
30
+ break;
31
+ }
32
+ }
33
+ return !preventInputRule;
34
+ };
35
+ }
36
+ const emDashRule = defineTextTransformRule({
37
+ on: /--/,
38
+ transform: () => "\u2014"
39
+ }), ellipsisRule = defineTextTransformRule({
40
+ on: /\.\.\./,
41
+ transform: () => "\u2026"
42
+ }), openingDoubleQuoteRule = defineTextTransformRule({
43
+ on: new RegExp(`(?:^|(?<=[\\s{[(<'"\\u2018\\u201C]))"`, "g"),
44
+ transform: () => "\u201C"
45
+ }), closingDoubleQuoteRule = defineTextTransformRule({
46
+ on: /"/g,
47
+ transform: () => "\u201D"
48
+ }), openingSingleQuoteRule = defineTextTransformRule({
49
+ on: new RegExp(`(?:^|(?<=[\\s{[(<'"\\u2018\\u201C]))'`, "g"),
50
+ transform: () => "\u2018"
51
+ }), closingSingleQuoteRule = defineTextTransformRule({
52
+ on: /'/g,
53
+ transform: () => "\u2019"
54
+ }), smartQuotesRules = [openingDoubleQuoteRule, closingDoubleQuoteRule, openingSingleQuoteRule, closingSingleQuoteRule], leftArrowRule = defineTextTransformRule({
55
+ on: /<-/,
56
+ transform: () => "\u2190"
57
+ }), rightArrowRule = defineTextTransformRule({
58
+ on: /->/,
59
+ transform: () => "\u2192"
60
+ }), copyrightRule = defineTextTransformRule({
61
+ on: /\(c\)/,
62
+ transform: () => "\xA9"
63
+ }), servicemarkRule = defineTextTransformRule({
64
+ on: /\(sm\)/,
65
+ transform: () => "\u2120"
66
+ }), trademarkRule = defineTextTransformRule({
67
+ on: /\(tm\)/,
68
+ transform: () => "\u2122"
69
+ }), registeredTrademarkRule = defineTextTransformRule({
70
+ on: /\(r\)/,
71
+ transform: () => "\xAE"
72
+ }), oneHalfRule = defineTextTransformRule({
73
+ on: /(?:^|\s)(1\/2)\s/,
74
+ transform: () => "\xBD"
75
+ }), plusMinusRule = defineTextTransformRule({
76
+ on: /\+\/-/,
77
+ transform: () => "\xB1"
78
+ }), notEqualRule = defineTextTransformRule({
79
+ on: /!=/,
80
+ transform: () => "\u2260"
81
+ }), laquoRule = defineTextTransformRule({
82
+ on: /<</,
83
+ transform: () => "\xAB"
84
+ }), raquoRule = defineTextTransformRule({
85
+ on: />>/,
86
+ transform: () => "\xBB"
87
+ }), multiplicationRule = defineTextTransformRule({
88
+ on: /\d+\s?([*x])\s?\d+/,
89
+ transform: () => "\xD7"
90
+ }), superscriptTwoRule = defineTextTransformRule({
91
+ on: /\^2/,
92
+ transform: () => "\xB2"
93
+ }), superscriptThreeRule = defineTextTransformRule({
94
+ on: /\^3/,
95
+ transform: () => "\xB3"
96
+ }), oneQuarterRule = defineTextTransformRule({
97
+ on: /(?:^|\s)(1\/4)\s/,
98
+ transform: () => "\xBC"
99
+ }), threeQuartersRule = defineTextTransformRule({
100
+ on: /(?:^|\s)(3\/4)\s/,
101
+ transform: () => "\xBE"
102
+ }), defaultRuleConfig = [{
103
+ name: "emDash",
104
+ rule: emDashRule,
105
+ state: "on"
106
+ }, {
107
+ name: "ellipsis",
108
+ rule: ellipsisRule,
109
+ state: "on"
110
+ }, {
111
+ name: "openingDoubleQuote",
112
+ rule: openingDoubleQuoteRule,
113
+ state: "on"
114
+ }, {
115
+ name: "closingDoubleQuote",
116
+ rule: closingDoubleQuoteRule,
117
+ state: "on"
118
+ }, {
119
+ name: "openingSingleQuote",
120
+ rule: openingSingleQuoteRule,
121
+ state: "on"
122
+ }, {
123
+ name: "closingSingleQuote",
124
+ rule: closingSingleQuoteRule,
125
+ state: "on"
126
+ }, {
127
+ name: "leftArrow",
128
+ rule: leftArrowRule,
129
+ state: "on"
130
+ }, {
131
+ name: "rightArrow",
132
+ rule: rightArrowRule,
133
+ state: "on"
134
+ }, {
135
+ name: "copyright",
136
+ rule: copyrightRule,
137
+ state: "on"
138
+ }, {
139
+ name: "trademark",
140
+ rule: trademarkRule,
141
+ state: "on"
142
+ }, {
143
+ name: "servicemark",
144
+ rule: servicemarkRule,
145
+ state: "on"
146
+ }, {
147
+ name: "registeredTrademark",
148
+ rule: registeredTrademarkRule,
149
+ state: "on"
150
+ }, {
151
+ name: "oneHalf",
152
+ rule: oneHalfRule,
153
+ state: "off"
154
+ }, {
155
+ name: "plusMinus",
156
+ rule: plusMinusRule,
157
+ state: "off"
158
+ }, {
159
+ name: "laquo",
160
+ rule: laquoRule,
161
+ state: "off"
162
+ }, {
163
+ name: "notEqual",
164
+ rule: notEqualRule,
165
+ state: "off"
166
+ }, {
167
+ name: "raquo",
168
+ rule: raquoRule,
169
+ state: "off"
170
+ }, {
171
+ name: "multiplication",
172
+ rule: multiplicationRule,
173
+ state: "off"
174
+ }, {
175
+ name: "superscriptTwo",
176
+ rule: superscriptTwoRule,
177
+ state: "off"
178
+ }, {
179
+ name: "superscriptThree",
180
+ rule: superscriptThreeRule,
181
+ state: "off"
182
+ }, {
183
+ name: "oneQuarter",
184
+ rule: oneQuarterRule,
185
+ state: "off"
186
+ }, {
187
+ name: "threeQuarters",
188
+ rule: threeQuartersRule,
189
+ state: "off"
190
+ }];
191
+ function TypographyPlugin(props) {
192
+ const $ = c(6);
193
+ let t0;
194
+ $[0] !== props.guard || $[1] !== props.rules ? (t0 = defaultRuleConfig.flatMap((rule) => props.rules && props.rules[rule.name] === "on" ? {
195
+ ...rule.rule,
196
+ guard: props.guard ?? _temp
197
+ } : props.rules && props.rules[rule.name] === "off" || rule.state === "off" ? [] : {
198
+ ...rule.rule,
199
+ guard: props.guard ?? _temp2
200
+ }), $[0] = props.guard, $[1] = props.rules, $[2] = t0) : t0 = $[2];
201
+ const configuredInputRules = t0;
202
+ let t1;
203
+ return $[3] !== configuredInputRules || $[4] !== props ? (t1 = /* @__PURE__ */ jsx(InputRulePlugin, { ...props, rules: configuredInputRules }), $[3] = configuredInputRules, $[4] = props, $[5] = t1) : t1 = $[5], t1;
204
+ }
205
+ function _temp2() {
206
+ return !0;
207
+ }
208
+ function _temp() {
209
+ return !0;
210
+ }
211
+ export {
212
+ TypographyPlugin,
213
+ closingDoubleQuoteRule,
214
+ closingSingleQuoteRule,
215
+ copyrightRule,
216
+ createDecoratorGuard,
217
+ ellipsisRule,
218
+ emDashRule,
219
+ laquoRule,
220
+ leftArrowRule,
221
+ multiplicationRule,
222
+ notEqualRule,
223
+ oneHalfRule,
224
+ oneQuarterRule,
225
+ openingDoubleQuoteRule,
226
+ openingSingleQuoteRule,
227
+ plusMinusRule,
228
+ raquoRule,
229
+ registeredTrademarkRule,
230
+ rightArrowRule,
231
+ servicemarkRule,
232
+ smartQuotesRules,
233
+ superscriptThreeRule,
234
+ superscriptTwoRule,
235
+ threeQuartersRule,
236
+ trademarkRule
237
+ };
238
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/create-decorator-guard.ts","../src/input-rules.typography.ts","../src/plugin.typography.tsx"],"sourcesContent":["import type {EditorSchema} from '@portabletext/editor'\nimport {\n getSelectedSpans,\n isActiveDecorator,\n} from '@portabletext/editor/selectors'\nimport type {InputRuleGuard} from '@portabletext/plugin-input-rule'\n\n/**\n * @public\n * Create an `InputRuleGuard` that can prevent the rule from running inside\n * certain decorators.\n *\n * @example\n * ```tsx\n * const guard = createDecoratorGuard({\n * decorators: ({schema}) => schema.decorators.flatMap((decorator) => decorator.name === 'code' ? [decorator.name] : []),\n * })\n *\n * <TypographyPlugin guard={guard} />\n * ```\n */\nexport function createDecoratorGuard(config: {\n decorators: ({schema}: {schema: EditorSchema}) => Array<string>\n}): InputRuleGuard {\n return ({snapshot, event}) => {\n const decorators = config.decorators({schema: snapshot.context.schema})\n\n if (decorators.length === 0) {\n return true\n }\n\n const matchedSpans = event.matches.flatMap((match) =>\n getSelectedSpans({\n ...snapshot,\n context: {\n ...snapshot.context,\n selection: match.selection,\n },\n }),\n )\n\n let preventInputRule = false\n\n for (const decorator of decorators) {\n if (isActiveDecorator(decorator)(snapshot)) {\n preventInputRule = true\n break\n }\n\n if (matchedSpans.some((span) => span.node.marks?.includes(decorator))) {\n preventInputRule = true\n break\n }\n }\n\n return !preventInputRule\n }\n}\n","import {\n defineTextTransformRule,\n type InputRule,\n} from '@portabletext/plugin-input-rule'\n\n/**\n * @public\n */\nexport const emDashRule = defineTextTransformRule({\n on: /--/,\n transform: () => '—',\n})\n\n/**\n * @public\n */\nexport const ellipsisRule = defineTextTransformRule({\n on: /\\.\\.\\./,\n transform: () => '…',\n})\n\n/**\n * @public\n */\nexport const openingDoubleQuoteRule = defineTextTransformRule({\n on: /(?:^|(?<=[\\s{[(<'\"\\u2018\\u201C]))\"/g,\n transform: () => '“',\n})\n\n/**\n * @public\n */\nexport const closingDoubleQuoteRule = defineTextTransformRule({\n on: /\"/g,\n transform: () => '”',\n})\n\n/**\n * @public\n */\nexport const openingSingleQuoteRule = defineTextTransformRule({\n on: /(?:^|(?<=[\\s{[(<'\"\\u2018\\u201C]))'/g,\n transform: () => '‘',\n})\n\n/**\n * @public\n */\nexport const closingSingleQuoteRule = defineTextTransformRule({\n on: /'/g,\n transform: () => '’',\n})\n\n/**\n * @public\n */\nexport const smartQuotesRules: Array<InputRule> = [\n openingDoubleQuoteRule,\n closingDoubleQuoteRule,\n openingSingleQuoteRule,\n closingSingleQuoteRule,\n]\n\n/**\n * @public\n */\nexport const leftArrowRule = defineTextTransformRule({\n on: /<-/,\n transform: () => '←',\n})\n\n/**\n * @public\n */\nexport const rightArrowRule = defineTextTransformRule({\n on: /->/,\n transform: () => '→',\n})\n\n/**\n * @public\n */\nexport const copyrightRule = defineTextTransformRule({\n on: /\\(c\\)/,\n transform: () => '©',\n})\n\n/**\n * @public\n */\nexport const servicemarkRule = defineTextTransformRule({\n on: /\\(sm\\)/,\n transform: () => '℠',\n})\n\n/**\n * @public\n */\nexport const trademarkRule = defineTextTransformRule({\n on: /\\(tm\\)/,\n transform: () => '™',\n})\n\n/**\n * @beta\n */\nexport const registeredTrademarkRule = defineTextTransformRule({\n on: /\\(r\\)/,\n transform: () => '®',\n})\n\n/**\n * @public\n */\nexport const oneHalfRule = defineTextTransformRule({\n on: /(?:^|\\s)(1\\/2)\\s/,\n transform: () => '½',\n})\n\n/**\n * @public\n */\nexport const plusMinusRule = defineTextTransformRule({\n on: /\\+\\/-/,\n transform: () => '±',\n})\n\n/**\n * @public\n */\nexport const notEqualRule = defineTextTransformRule({\n on: /!=/,\n transform: () => '≠',\n})\n\n/**\n * @public\n */\nexport const laquoRule = defineTextTransformRule({\n on: /<</,\n transform: () => '«',\n})\n\n/**\n * @public\n */\nexport const raquoRule = defineTextTransformRule({\n on: />>/,\n transform: () => '»',\n})\n\n/**\n * @public\n */\nexport const multiplicationRule = defineTextTransformRule({\n on: /\\d+\\s?([*x])\\s?\\d+/,\n transform: () => '×',\n})\n\n/**\n * @public\n */\nexport const superscriptTwoRule = defineTextTransformRule({\n on: /\\^2/,\n transform: () => '²',\n})\n\n/**\n * @public\n */\nexport const superscriptThreeRule = defineTextTransformRule({\n on: /\\^3/,\n transform: () => '³',\n})\n\n/**\n * @public\n */\nexport const oneQuarterRule = defineTextTransformRule({\n on: /(?:^|\\s)(1\\/4)\\s/,\n transform: () => '¼',\n})\n\n/**\n * @public\n */\nexport const threeQuartersRule = defineTextTransformRule({\n on: /(?:^|\\s)(3\\/4)\\s/,\n transform: () => '¾',\n})\n","import {\n InputRulePlugin,\n type InputRule,\n type InputRuleGuard,\n} from '@portabletext/plugin-input-rule'\nimport {useMemo} from 'react'\nimport {\n closingDoubleQuoteRule,\n closingSingleQuoteRule,\n copyrightRule,\n ellipsisRule,\n emDashRule,\n laquoRule,\n leftArrowRule,\n multiplicationRule,\n notEqualRule,\n oneHalfRule,\n oneQuarterRule,\n openingDoubleQuoteRule,\n openingSingleQuoteRule,\n plusMinusRule,\n raquoRule,\n registeredTrademarkRule,\n rightArrowRule,\n servicemarkRule,\n superscriptThreeRule,\n superscriptTwoRule,\n threeQuartersRule,\n trademarkRule,\n} from './input-rules.typography'\n\n/**\n * @public\n */\nexport type TypographyPluginProps = {\n guard?: InputRuleGuard\n /**\n * Configure which rules to enable or disable. Ordinary rules like `emDash` and `ellipsis` are enabled by default.\n * Less common rules like `multiplication` are disabled by default.\n */\n rules?: {\n /**\n * @defaultValue 'on'\n */\n emDash?: 'on' | 'off'\n /**\n * @defaultValue 'on'\n */\n ellipsis?: 'on' | 'off'\n /**\n * @defaultValue 'on'\n */\n openingDoubleQuote?: 'on' | 'off'\n /**\n * @defaultValue 'on'\n */\n closingDoubleQuote?: 'on' | 'off'\n /**\n * @defaultValue 'on'\n */\n openingSingleQuote?: 'on' | 'off'\n /**\n * @defaultValue 'on'\n */\n closingSingleQuote?: 'on' | 'off'\n /**\n * @defaultValue 'on'\n */\n leftArrow?: 'on' | 'off'\n /**\n * @defaultValue 'on'\n */\n rightArrow?: 'on' | 'off'\n /**\n * @defaultValue 'on'\n */\n copyright?: 'on' | 'off'\n /**\n * @defaultValue 'on'\n */\n trademark?: 'on' | 'off'\n /**\n * @defaultValue 'on'\n */\n servicemark?: 'on' | 'off'\n /**\n * @defaultValue 'on'\n */\n registeredTrademark?: 'on' | 'off'\n /**\n * @defaultValue 'off'\n */\n oneHalf?: 'on' | 'off'\n /**\n * @defaultValue 'off'\n */\n plusMinus?: 'on' | 'off'\n /**\n * @defaultValue 'off'\n */\n notEqual?: 'on' | 'off'\n /**\n * @defaultValue 'off'\n */\n laquo?: 'on' | 'off'\n /**\n * @defaultValue 'off'\n */\n raquo?: 'on' | 'off'\n /**\n * @defaultValue 'off'\n */\n multiplication?: 'on' | 'off'\n /**\n * @defaultValue 'off'\n */\n superscriptTwo?: 'on' | 'off'\n /**\n * @defaultValue 'off'\n */\n superscriptThree?: 'on' | 'off'\n /**\n * @defaultValue 'off'\n */\n oneQuarter?: 'on' | 'off'\n /**\n * @defaultValue 'off'\n */\n threeQuarters?: 'on' | 'off'\n }\n}\n\ntype RuleName = keyof NonNullable<TypographyPluginProps['rules']>\n\nconst defaultRuleConfig: Array<{\n name: RuleName\n rule: InputRule\n state: 'on' | 'off'\n}> = [\n {name: 'emDash', rule: emDashRule, state: 'on'},\n {name: 'ellipsis', rule: ellipsisRule, state: 'on'},\n {name: 'openingDoubleQuote', rule: openingDoubleQuoteRule, state: 'on'},\n {name: 'closingDoubleQuote', rule: closingDoubleQuoteRule, state: 'on'},\n {name: 'openingSingleQuote', rule: openingSingleQuoteRule, state: 'on'},\n {name: 'closingSingleQuote', rule: closingSingleQuoteRule, state: 'on'},\n {name: 'leftArrow', rule: leftArrowRule, state: 'on'},\n {name: 'rightArrow', rule: rightArrowRule, state: 'on'},\n {name: 'copyright', rule: copyrightRule, state: 'on'},\n {name: 'trademark', rule: trademarkRule, state: 'on'},\n {name: 'servicemark', rule: servicemarkRule, state: 'on'},\n {name: 'registeredTrademark', rule: registeredTrademarkRule, state: 'on'},\n {name: 'oneHalf', rule: oneHalfRule, state: 'off'},\n {name: 'plusMinus', rule: plusMinusRule, state: 'off'},\n {name: 'laquo', rule: laquoRule, state: 'off'},\n {name: 'notEqual', rule: notEqualRule, state: 'off'},\n {name: 'raquo', rule: raquoRule, state: 'off'},\n {name: 'multiplication', rule: multiplicationRule, state: 'off'},\n {name: 'superscriptTwo', rule: superscriptTwoRule, state: 'off'},\n {name: 'superscriptThree', rule: superscriptThreeRule, state: 'off'},\n {name: 'oneQuarter', rule: oneQuarterRule, state: 'off'},\n {name: 'threeQuarters', rule: threeQuartersRule, state: 'off'},\n]\n\n/**\n * @public\n */\nexport function TypographyPlugin(props: TypographyPluginProps) {\n const configuredInputRules = useMemo(\n () =>\n defaultRuleConfig.flatMap((rule) =>\n props.rules && props.rules[rule.name] === 'on'\n ? {...rule.rule, guard: props.guard ?? (() => true)}\n : (props.rules && props.rules[rule.name] === 'off') ||\n rule.state === 'off'\n ? []\n : {...rule.rule, guard: props.guard ?? (() => true)},\n ),\n [props.guard, props.rules],\n )\n\n return <InputRulePlugin {...props} rules={configuredInputRules} />\n}\n"],"names":["createDecoratorGuard","config","snapshot","event","decorators","schema","context","length","matchedSpans","matches","flatMap","match","getSelectedSpans","selection","preventInputRule","decorator","isActiveDecorator","some","span","node","marks","includes","emDashRule","defineTextTransformRule","on","transform","ellipsisRule","openingDoubleQuoteRule","closingDoubleQuoteRule","openingSingleQuoteRule","closingSingleQuoteRule","smartQuotesRules","leftArrowRule","rightArrowRule","copyrightRule","servicemarkRule","trademarkRule","registeredTrademarkRule","oneHalfRule","plusMinusRule","notEqualRule","laquoRule","raquoRule","multiplicationRule","superscriptTwoRule","superscriptThreeRule","oneQuarterRule","threeQuartersRule","defaultRuleConfig","name","rule","state","TypographyPlugin","props","$","_c","t0","guard","rules","_temp","_temp2","configuredInputRules","t1"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,84 @@
1
+ {
2
+ "name": "@portabletext/plugin-typography",
3
+ "version": "0.0.1",
4
+ "description": "Automatically transform text to typographic variants",
5
+ "keywords": [
6
+ "portabletext",
7
+ "plugin",
8
+ "typography"
9
+ ],
10
+ "homepage": "https://www.portabletext.org/",
11
+ "bugs": {
12
+ "url": "https://github.com/portabletext/editor/issues"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "https://github.com/portabletext/editor.git",
17
+ "directory": "packages/plugin-typography"
18
+ },
19
+ "license": "MIT",
20
+ "author": "Sanity.io <hello@sanity.io>",
21
+ "sideEffects": false,
22
+ "type": "module",
23
+ "exports": {
24
+ ".": {
25
+ "source": "./src/index.ts",
26
+ "import": "./dist/index.js",
27
+ "require": "./dist/index.cjs",
28
+ "default": "./dist/index.js"
29
+ },
30
+ "./package.json": "./package.json"
31
+ },
32
+ "main": "./dist/index.cjs",
33
+ "module": "./dist/index.js",
34
+ "types": "./dist/index.d.ts",
35
+ "files": [
36
+ "dist",
37
+ "src"
38
+ ],
39
+ "dependencies": {
40
+ "react-compiler-runtime": "19.1.0-rc.3",
41
+ "@portabletext/plugin-input-rule": "~0.1.0"
42
+ },
43
+ "devDependencies": {
44
+ "@sanity/pkg-utils": "^8.1.4",
45
+ "@types/react": "^19.1.11",
46
+ "@vitejs/plugin-react": "^5.0.3",
47
+ "babel-plugin-react-compiler": "19.1.0-rc.3",
48
+ "eslint": "^9.34.0",
49
+ "eslint-formatter-gha": "^1.6.0",
50
+ "eslint-plugin-react-hooks": "6.0.0-rc.2",
51
+ "react": "^19.1.1",
52
+ "typescript": "5.9.3",
53
+ "typescript-eslint": "^8.41.0",
54
+ "vitest": "^3.2.4",
55
+ "@portabletext/editor": "^2.13.5",
56
+ "@portabletext/schema": "^1.2.0",
57
+ "racejar": "1.3.1"
58
+ },
59
+ "peerDependencies": {
60
+ "@portabletext/editor": "^2.13.5",
61
+ "react": "^19.1.1"
62
+ },
63
+ "publishConfig": {
64
+ "access": "public"
65
+ },
66
+ "scripts": {
67
+ "build": "pkg-utils build --strict --check --clean",
68
+ "check:lint": "biome lint .",
69
+ "check:react-compiler": "eslint --cache .",
70
+ "check:types": "tsc",
71
+ "check:types:watch": "tsc --watch",
72
+ "clean": "del .turbo && del lib && del node_modules",
73
+ "dev": "pkg-utils watch",
74
+ "lint:fix": "biome lint --write .",
75
+ "test": "vitest --run",
76
+ "test:browser": "vitest --run --project browser",
77
+ "test:browser:chromium": "vitest run --project \"browser (chromium)\"",
78
+ "test:browser:chromium:watch": "vitest watch --project \"browser (chromium)\"",
79
+ "test:browser:firefox": "vitest run --project \"browser (firefox)\"",
80
+ "test:browser:firefox:watch": "vitest watch --project \"browser (firefox)\"",
81
+ "test:browser:webkit": "vitest run --project \"browser (webkit)\"",
82
+ "test:browser:webkit:watch": "vitest watch --project \"browser (webkit)\""
83
+ }
84
+ }
@@ -0,0 +1,58 @@
1
+ import type {EditorSchema} from '@portabletext/editor'
2
+ import {
3
+ getSelectedSpans,
4
+ isActiveDecorator,
5
+ } from '@portabletext/editor/selectors'
6
+ import type {InputRuleGuard} from '@portabletext/plugin-input-rule'
7
+
8
+ /**
9
+ * @public
10
+ * Create an `InputRuleGuard` that can prevent the rule from running inside
11
+ * certain decorators.
12
+ *
13
+ * @example
14
+ * ```tsx
15
+ * const guard = createDecoratorGuard({
16
+ * decorators: ({schema}) => schema.decorators.flatMap((decorator) => decorator.name === 'code' ? [decorator.name] : []),
17
+ * })
18
+ *
19
+ * <TypographyPlugin guard={guard} />
20
+ * ```
21
+ */
22
+ export function createDecoratorGuard(config: {
23
+ decorators: ({schema}: {schema: EditorSchema}) => Array<string>
24
+ }): InputRuleGuard {
25
+ return ({snapshot, event}) => {
26
+ const decorators = config.decorators({schema: snapshot.context.schema})
27
+
28
+ if (decorators.length === 0) {
29
+ return true
30
+ }
31
+
32
+ const matchedSpans = event.matches.flatMap((match) =>
33
+ getSelectedSpans({
34
+ ...snapshot,
35
+ context: {
36
+ ...snapshot.context,
37
+ selection: match.selection,
38
+ },
39
+ }),
40
+ )
41
+
42
+ let preventInputRule = false
43
+
44
+ for (const decorator of decorators) {
45
+ if (isActiveDecorator(decorator)(snapshot)) {
46
+ preventInputRule = true
47
+ break
48
+ }
49
+
50
+ if (matchedSpans.some((span) => span.node.marks?.includes(decorator))) {
51
+ preventInputRule = true
52
+ break
53
+ }
54
+ }
55
+
56
+ return !preventInputRule
57
+ }
58
+ }