@wordpress/format-library 3.0.4 → 3.0.5
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.
- package/build/bold/index.js +5 -2
- package/build/bold/index.js.map +1 -1
- package/build/code/index.js +4 -2
- package/build/code/index.js.map +1 -1
- package/build/italic/index.js +5 -2
- package/build/italic/index.js.map +1 -1
- package/build/keyboard/index.js +4 -2
- package/build/keyboard/index.js.map +1 -1
- package/build/link/inline.js +56 -5
- package/build/link/inline.js.map +1 -1
- package/build/link/utils.js +112 -0
- package/build/link/utils.js.map +1 -1
- package/build/strikethrough/index.js +4 -2
- package/build/strikethrough/index.js.map +1 -1
- package/build/subscript/index.js +4 -2
- package/build/subscript/index.js.map +1 -1
- package/build/superscript/index.js +4 -2
- package/build/superscript/index.js.map +1 -1
- package/build/text-color/index.js +2 -1
- package/build/text-color/index.js.map +1 -1
- package/build/text-color/inline.js +9 -2
- package/build/text-color/inline.js.map +1 -1
- package/build/underline/index.js +4 -2
- package/build/underline/index.js.map +1 -1
- package/build-module/bold/index.js +5 -2
- package/build-module/bold/index.js.map +1 -1
- package/build-module/code/index.js +4 -2
- package/build-module/code/index.js.map +1 -1
- package/build-module/italic/index.js +5 -2
- package/build-module/italic/index.js.map +1 -1
- package/build-module/keyboard/index.js +4 -2
- package/build-module/keyboard/index.js.map +1 -1
- package/build-module/link/inline.js +58 -7
- package/build-module/link/inline.js.map +1 -1
- package/build-module/link/utils.js +110 -1
- package/build-module/link/utils.js.map +1 -1
- package/build-module/strikethrough/index.js +4 -2
- package/build-module/strikethrough/index.js.map +1 -1
- package/build-module/subscript/index.js +4 -2
- package/build-module/subscript/index.js.map +1 -1
- package/build-module/superscript/index.js +4 -2
- package/build-module/superscript/index.js.map +1 -1
- package/build-module/text-color/index.js +2 -1
- package/build-module/text-color/index.js.map +1 -1
- package/build-module/text-color/inline.js +10 -3
- package/build-module/text-color/inline.js.map +1 -1
- package/build-module/underline/index.js +6 -2
- package/build-module/underline/index.js.map +1 -1
- package/package.json +10 -10
- package/src/bold/index.js +2 -2
- package/src/code/index.js +2 -1
- package/src/italic/index.js +2 -2
- package/src/keyboard/index.js +2 -1
- package/src/link/inline.js +67 -5
- package/src/link/test/utils.js +362 -1
- package/src/link/utils.js +132 -1
- package/src/strikethrough/index.js +2 -1
- package/src/subscript/index.js +2 -1
- package/src/superscript/index.js +2 -1
- package/src/text-color/index.js +1 -0
- package/src/text-color/inline.js +12 -1
- package/src/underline/index.js +3 -1
package/src/link/test/utils.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Internal dependencies
|
|
3
3
|
*/
|
|
4
|
-
import { isValidHref } from '../utils';
|
|
4
|
+
import { isValidHref, getFormatBoundary } from '../utils';
|
|
5
5
|
|
|
6
6
|
describe( 'isValidHref', () => {
|
|
7
7
|
it( 'returns true if the href cannot be recognised as a url or an anchor link', () => {
|
|
@@ -96,3 +96,364 @@ describe( 'isValidHref', () => {
|
|
|
96
96
|
} );
|
|
97
97
|
} );
|
|
98
98
|
} );
|
|
99
|
+
|
|
100
|
+
describe( 'getFormatBoundary', () => {
|
|
101
|
+
const boldFormat = {
|
|
102
|
+
type: 'core/bold',
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const italicFormat = {
|
|
106
|
+
type: 'core/italic',
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const linkFormat = {
|
|
110
|
+
type: 'core/link',
|
|
111
|
+
attributes: {
|
|
112
|
+
url: 'http://www.wordpress.org',
|
|
113
|
+
type: 'URL',
|
|
114
|
+
id: 'www.wordpress.org',
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
describe( 'Invalid values', () => {
|
|
119
|
+
it( 'should return empty bounds if value contains no formats', () => {
|
|
120
|
+
const record = {
|
|
121
|
+
formats: [], // no formats here!
|
|
122
|
+
text: 'Lorem ipsum dolor.',
|
|
123
|
+
start: 8,
|
|
124
|
+
end: 8,
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
expect(
|
|
128
|
+
getFormatBoundary( record, { type: 'core/link' } )
|
|
129
|
+
).toEqual( {
|
|
130
|
+
start: null,
|
|
131
|
+
end: null,
|
|
132
|
+
} );
|
|
133
|
+
} );
|
|
134
|
+
|
|
135
|
+
it.each( [
|
|
136
|
+
[ 5, 12 ],
|
|
137
|
+
[ 11, 12 ],
|
|
138
|
+
] )(
|
|
139
|
+
'should return empty bounds if both start and end indexes do not contain the target format',
|
|
140
|
+
() => {
|
|
141
|
+
const record = {
|
|
142
|
+
formats: [
|
|
143
|
+
null,
|
|
144
|
+
[ italicFormat ],
|
|
145
|
+
[ italicFormat ],
|
|
146
|
+
[ italicFormat ],
|
|
147
|
+
null,
|
|
148
|
+
null, // 5
|
|
149
|
+
[ linkFormat, italicFormat ], // 6
|
|
150
|
+
[ linkFormat ],
|
|
151
|
+
[ linkFormat, boldFormat ],
|
|
152
|
+
[ linkFormat, boldFormat ],
|
|
153
|
+
[ linkFormat, italicFormat ], // 10
|
|
154
|
+
null, // 11
|
|
155
|
+
[ boldFormat ], // 12
|
|
156
|
+
[ boldFormat ],
|
|
157
|
+
[ boldFormat ],
|
|
158
|
+
[ boldFormat ],
|
|
159
|
+
null,
|
|
160
|
+
null,
|
|
161
|
+
],
|
|
162
|
+
|
|
163
|
+
text: 'Lorem ipsum dolor.',
|
|
164
|
+
start: 5, // no format here
|
|
165
|
+
end: 12, // format here but it doesn't match the target format
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
expect(
|
|
169
|
+
getFormatBoundary( record, { type: 'core/link' } )
|
|
170
|
+
).toEqual( {
|
|
171
|
+
start: null,
|
|
172
|
+
end: null,
|
|
173
|
+
} );
|
|
174
|
+
}
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
it.each( [
|
|
178
|
+
[
|
|
179
|
+
"start and end are beyond the length of the provided value's formats",
|
|
180
|
+
[ 19, 22 ],
|
|
181
|
+
],
|
|
182
|
+
[ 'start and end are less than 0', [ -1, -2 ] ],
|
|
183
|
+
] )(
|
|
184
|
+
'should return empty bounds if %s',
|
|
185
|
+
( _ignored, [ start, end ] ) => {
|
|
186
|
+
const record = {
|
|
187
|
+
formats: [
|
|
188
|
+
null,
|
|
189
|
+
[ italicFormat ],
|
|
190
|
+
[ italicFormat ],
|
|
191
|
+
[ italicFormat ],
|
|
192
|
+
null,
|
|
193
|
+
null, // 5
|
|
194
|
+
[ linkFormat, italicFormat ], // 6
|
|
195
|
+
[ linkFormat ],
|
|
196
|
+
[ linkFormat, boldFormat ],
|
|
197
|
+
[ linkFormat, boldFormat ],
|
|
198
|
+
[ linkFormat, italicFormat ], // 10
|
|
199
|
+
null, // 11
|
|
200
|
+
[ boldFormat ], // 12
|
|
201
|
+
[ boldFormat ],
|
|
202
|
+
[ boldFormat ],
|
|
203
|
+
[ boldFormat ],
|
|
204
|
+
null,
|
|
205
|
+
null, // 17
|
|
206
|
+
],
|
|
207
|
+
|
|
208
|
+
text: 'Lorem ipsum dolor.',
|
|
209
|
+
start,
|
|
210
|
+
end,
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
expect(
|
|
214
|
+
getFormatBoundary( record, { type: 'core/link' } )
|
|
215
|
+
).toEqual( {
|
|
216
|
+
start: null,
|
|
217
|
+
end: null,
|
|
218
|
+
} );
|
|
219
|
+
}
|
|
220
|
+
);
|
|
221
|
+
} );
|
|
222
|
+
|
|
223
|
+
describe( 'Collapsed values', () => {
|
|
224
|
+
it.each( [
|
|
225
|
+
[ 'inside', [ 8, 8 ] ],
|
|
226
|
+
[ 'start', [ 6, 6 ] ],
|
|
227
|
+
[ 'end', [ 10, 10 ] ],
|
|
228
|
+
[ 'just inside the start', [ 7, 7 ] ],
|
|
229
|
+
[ 'just inside the end', [ 9, 9 ] ],
|
|
230
|
+
] )(
|
|
231
|
+
'should find bounds of a format from %s of a collapsed RichTextValue',
|
|
232
|
+
( _ignored, [ start, end ] ) => {
|
|
233
|
+
const record = {
|
|
234
|
+
formats: [
|
|
235
|
+
null,
|
|
236
|
+
[ italicFormat ],
|
|
237
|
+
[ italicFormat ],
|
|
238
|
+
[ italicFormat ],
|
|
239
|
+
null,
|
|
240
|
+
null,
|
|
241
|
+
[ linkFormat, italicFormat ], // 6
|
|
242
|
+
[ linkFormat ],
|
|
243
|
+
[ linkFormat, boldFormat ],
|
|
244
|
+
[ linkFormat, boldFormat ],
|
|
245
|
+
[ linkFormat, italicFormat ], // 10
|
|
246
|
+
],
|
|
247
|
+
|
|
248
|
+
text: 'Lorem ipsum dolor.',
|
|
249
|
+
start,
|
|
250
|
+
end,
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
expect(
|
|
254
|
+
getFormatBoundary( record, { type: 'core/link' } )
|
|
255
|
+
).toEqual( {
|
|
256
|
+
start: 6,
|
|
257
|
+
end: 10,
|
|
258
|
+
} );
|
|
259
|
+
}
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
it( 'should find bounds of a format from just outside the end of a collapsed RichTextValue', () => {
|
|
263
|
+
// This is an edge case which will occur if you create a format, then place
|
|
264
|
+
// the caret just before the format and hit the back ARROW key. The resulting
|
|
265
|
+
// value object will have start and end +1 beyond the edge of the format boundary.
|
|
266
|
+
// The code under test here has to cope with that by searching for formats -1 back
|
|
267
|
+
// from the end value.
|
|
268
|
+
const record = {
|
|
269
|
+
formats: [
|
|
270
|
+
null,
|
|
271
|
+
[ italicFormat ],
|
|
272
|
+
[ italicFormat ],
|
|
273
|
+
[ italicFormat ],
|
|
274
|
+
null,
|
|
275
|
+
null,
|
|
276
|
+
[ linkFormat, italicFormat ], // 6
|
|
277
|
+
[ linkFormat ],
|
|
278
|
+
[ linkFormat, boldFormat ],
|
|
279
|
+
[ linkFormat, boldFormat ],
|
|
280
|
+
[ linkFormat, italicFormat ], // 10
|
|
281
|
+
],
|
|
282
|
+
|
|
283
|
+
text: 'Lorem ipsum dolor.',
|
|
284
|
+
start: 11, // +1 beyond the end of the formats
|
|
285
|
+
end: 11, // +1 beyond the end of the formats
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
expect(
|
|
289
|
+
getFormatBoundary( record, { type: 'core/link' } )
|
|
290
|
+
).toEqual( {
|
|
291
|
+
start: 6,
|
|
292
|
+
end: 10,
|
|
293
|
+
} );
|
|
294
|
+
} );
|
|
295
|
+
} );
|
|
296
|
+
|
|
297
|
+
describe( 'Non-collapsed values', () => {
|
|
298
|
+
it.each( [
|
|
299
|
+
[ 'at the bounds', [ 6, 10 ] ],
|
|
300
|
+
[ 'inside the bounds', [ 7, 8 ] ],
|
|
301
|
+
] )(
|
|
302
|
+
'should find bounds of a format beginning %s of a non-collapsed RichTextValue',
|
|
303
|
+
( _ignored, [ start, end ] ) => {
|
|
304
|
+
const record = {
|
|
305
|
+
formats: [
|
|
306
|
+
null,
|
|
307
|
+
[ italicFormat ],
|
|
308
|
+
[ italicFormat ],
|
|
309
|
+
[ italicFormat ],
|
|
310
|
+
null,
|
|
311
|
+
null,
|
|
312
|
+
[ linkFormat, italicFormat ], // 6
|
|
313
|
+
[ linkFormat ],
|
|
314
|
+
[ linkFormat, boldFormat ],
|
|
315
|
+
[ linkFormat, boldFormat ],
|
|
316
|
+
[ linkFormat, italicFormat ], // 10
|
|
317
|
+
null,
|
|
318
|
+
null,
|
|
319
|
+
[ boldFormat ],
|
|
320
|
+
[ boldFormat ],
|
|
321
|
+
[ boldFormat ],
|
|
322
|
+
null,
|
|
323
|
+
null,
|
|
324
|
+
],
|
|
325
|
+
|
|
326
|
+
text: 'Lorem ipsum dolor.',
|
|
327
|
+
start,
|
|
328
|
+
end,
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
expect(
|
|
332
|
+
getFormatBoundary( record, { type: 'core/link' } )
|
|
333
|
+
).toEqual( {
|
|
334
|
+
start: 6,
|
|
335
|
+
end: 10,
|
|
336
|
+
} );
|
|
337
|
+
}
|
|
338
|
+
);
|
|
339
|
+
} );
|
|
340
|
+
|
|
341
|
+
it( 'should find bounds of a format which starts at zeroth index where start/end pointers are at 0', () => {
|
|
342
|
+
const record = {
|
|
343
|
+
formats: [
|
|
344
|
+
[ linkFormat ], // 0 (th zeroth index)
|
|
345
|
+
[ linkFormat ],
|
|
346
|
+
[ linkFormat ],
|
|
347
|
+
[ linkFormat ],
|
|
348
|
+
[ linkFormat ],
|
|
349
|
+
[ linkFormat ], // 5
|
|
350
|
+
[ boldFormat ],
|
|
351
|
+
[ boldFormat ],
|
|
352
|
+
null,
|
|
353
|
+
null,
|
|
354
|
+
null,
|
|
355
|
+
null,
|
|
356
|
+
null,
|
|
357
|
+
null,
|
|
358
|
+
null,
|
|
359
|
+
[ boldFormat ],
|
|
360
|
+
[ boldFormat ],
|
|
361
|
+
[ boldFormat ],
|
|
362
|
+
null,
|
|
363
|
+
null,
|
|
364
|
+
null,
|
|
365
|
+
null,
|
|
366
|
+
null,
|
|
367
|
+
null,
|
|
368
|
+
null,
|
|
369
|
+
[ italicFormat ],
|
|
370
|
+
[ italicFormat ],
|
|
371
|
+
[ italicFormat ],
|
|
372
|
+
[ italicFormat ],
|
|
373
|
+
[ italicFormat ],
|
|
374
|
+
null,
|
|
375
|
+
],
|
|
376
|
+
|
|
377
|
+
text: "Lorem ok let's try again dolor.",
|
|
378
|
+
start: 0,
|
|
379
|
+
end: 0,
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
expect( getFormatBoundary( record, { type: 'core/link' } ) ).toEqual( {
|
|
383
|
+
start: 0,
|
|
384
|
+
end: 5,
|
|
385
|
+
} );
|
|
386
|
+
} );
|
|
387
|
+
|
|
388
|
+
describe( 'Single value out of bounds', () => {
|
|
389
|
+
it.each( [
|
|
390
|
+
[ 'start is outside the boundary but end is inside', [ 1, 4 ] ],
|
|
391
|
+
[ 'end is outside the boundary but start is inside', [ 4, 10 ] ],
|
|
392
|
+
[
|
|
393
|
+
'end is withins bounds but is less than start (inverted)',
|
|
394
|
+
[ 4, 1 ],
|
|
395
|
+
],
|
|
396
|
+
[ 'start is negative but end is within bounds', [ -1000, 4 ] ],
|
|
397
|
+
[ 'end is negative but start is within bounds', [ 4, -1000 ] ],
|
|
398
|
+
] )( 'should return bounds when %s', ( _ignored, [ start, end ] ) => {
|
|
399
|
+
const record = {
|
|
400
|
+
formats: [
|
|
401
|
+
[],
|
|
402
|
+
[],
|
|
403
|
+
[],
|
|
404
|
+
[],
|
|
405
|
+
[ boldFormat ], // 4
|
|
406
|
+
[ boldFormat ],
|
|
407
|
+
[ boldFormat ], // 6
|
|
408
|
+
[],
|
|
409
|
+
[],
|
|
410
|
+
],
|
|
411
|
+
text: 'Lorem ipsum dolor.',
|
|
412
|
+
start,
|
|
413
|
+
end,
|
|
414
|
+
};
|
|
415
|
+
|
|
416
|
+
expect(
|
|
417
|
+
getFormatBoundary( record, { type: 'core/bold' } )
|
|
418
|
+
).toEqual( {
|
|
419
|
+
start: 4,
|
|
420
|
+
end: 6,
|
|
421
|
+
} );
|
|
422
|
+
} );
|
|
423
|
+
} );
|
|
424
|
+
|
|
425
|
+
it( 'should respect startIndex and endIndex arguments when seeking boundary', () => {
|
|
426
|
+
const startIndex = 1;
|
|
427
|
+
const endIndex = 3;
|
|
428
|
+
|
|
429
|
+
const record = {
|
|
430
|
+
formats: [
|
|
431
|
+
[ boldFormat ],
|
|
432
|
+
[ boldFormat ],
|
|
433
|
+
[ boldFormat ],
|
|
434
|
+
[ boldFormat ],
|
|
435
|
+
[ boldFormat ],
|
|
436
|
+
[],
|
|
437
|
+
[],
|
|
438
|
+
[],
|
|
439
|
+
[],
|
|
440
|
+
[],
|
|
441
|
+
],
|
|
442
|
+
text: 'Lorem ipsum dolor.',
|
|
443
|
+
start: 10, // the value start is outside the format
|
|
444
|
+
end: 10, // the value end is outside the format
|
|
445
|
+
};
|
|
446
|
+
|
|
447
|
+
expect(
|
|
448
|
+
getFormatBoundary(
|
|
449
|
+
record,
|
|
450
|
+
{ type: 'core/bold' },
|
|
451
|
+
startIndex,
|
|
452
|
+
endIndex
|
|
453
|
+
)
|
|
454
|
+
).toEqual( {
|
|
455
|
+
start: 0,
|
|
456
|
+
end: 4,
|
|
457
|
+
} );
|
|
458
|
+
} );
|
|
459
|
+
} );
|
package/src/link/utils.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
|
-
import { startsWith } from 'lodash';
|
|
4
|
+
import { startsWith, find, partialRight } from 'lodash';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* WordPress dependencies
|
|
@@ -111,3 +111,134 @@ export function createLinkFormat( { url, type, id, opensInNewWindow } ) {
|
|
|
111
111
|
|
|
112
112
|
return format;
|
|
113
113
|
}
|
|
114
|
+
|
|
115
|
+
/* eslint-disable jsdoc/no-undefined-types */
|
|
116
|
+
/**
|
|
117
|
+
* Get the start and end boundaries of a given format from a rich text value.
|
|
118
|
+
*
|
|
119
|
+
*
|
|
120
|
+
* @param {RichTextValue} value the rich text value to interrogate.
|
|
121
|
+
* @param {string} format the identifier for the target format (e.g. `core/link`, `core/bold`).
|
|
122
|
+
* @param {number?} startIndex optional startIndex to seek from.
|
|
123
|
+
* @param {number?} endIndex optional endIndex to seek from.
|
|
124
|
+
* @return {Object} object containing start and end values for the given format.
|
|
125
|
+
*/
|
|
126
|
+
/* eslint-enable jsdoc/no-undefined-types */
|
|
127
|
+
export function getFormatBoundary(
|
|
128
|
+
value,
|
|
129
|
+
format,
|
|
130
|
+
startIndex = value.start,
|
|
131
|
+
endIndex = value.end
|
|
132
|
+
) {
|
|
133
|
+
const EMPTY_BOUNDARIES = {
|
|
134
|
+
start: null,
|
|
135
|
+
end: null,
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const { formats } = value;
|
|
139
|
+
let targetFormat;
|
|
140
|
+
let initialIndex;
|
|
141
|
+
|
|
142
|
+
if ( ! formats?.length ) {
|
|
143
|
+
return EMPTY_BOUNDARIES;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Clone formats to avoid modifying source formats.
|
|
147
|
+
const newFormats = formats.slice();
|
|
148
|
+
|
|
149
|
+
const formatAtStart = find( newFormats[ startIndex ], {
|
|
150
|
+
type: format.type,
|
|
151
|
+
} );
|
|
152
|
+
|
|
153
|
+
const formatAtEnd = find( newFormats[ endIndex ], {
|
|
154
|
+
type: format.type,
|
|
155
|
+
} );
|
|
156
|
+
|
|
157
|
+
const formatAtEndMinusOne = find( newFormats[ endIndex - 1 ], {
|
|
158
|
+
type: format.type,
|
|
159
|
+
} );
|
|
160
|
+
|
|
161
|
+
if ( !! formatAtStart ) {
|
|
162
|
+
// Set values to conform to "start"
|
|
163
|
+
targetFormat = formatAtStart;
|
|
164
|
+
initialIndex = startIndex;
|
|
165
|
+
} else if ( !! formatAtEnd ) {
|
|
166
|
+
// Set values to conform to "end"
|
|
167
|
+
targetFormat = formatAtEnd;
|
|
168
|
+
initialIndex = endIndex;
|
|
169
|
+
} else if ( !! formatAtEndMinusOne ) {
|
|
170
|
+
// This is an edge case which will occur if you create a format, then place
|
|
171
|
+
// the caret just before the format and hit the back ARROW key. The resulting
|
|
172
|
+
// value object will have start and end +1 beyond the edge of the format boundary.
|
|
173
|
+
targetFormat = formatAtEndMinusOne;
|
|
174
|
+
initialIndex = endIndex - 1;
|
|
175
|
+
} else {
|
|
176
|
+
return EMPTY_BOUNDARIES;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const index = newFormats[ initialIndex ].indexOf( targetFormat );
|
|
180
|
+
|
|
181
|
+
const walkingArgs = [ newFormats, initialIndex, targetFormat, index ];
|
|
182
|
+
|
|
183
|
+
// Walk the startIndex "backwards" to the leading "edge" of the matching format.
|
|
184
|
+
startIndex = walkToStart( ...walkingArgs );
|
|
185
|
+
|
|
186
|
+
// Walk the endIndex "forwards" until the trailing "edge" of the matching format.
|
|
187
|
+
endIndex = walkToEnd( ...walkingArgs );
|
|
188
|
+
|
|
189
|
+
// Safe guard: start index cannot be less than 0
|
|
190
|
+
startIndex = startIndex < 0 ? 0 : startIndex;
|
|
191
|
+
|
|
192
|
+
// // Return the indicies of the "edges" as the boundaries.
|
|
193
|
+
return {
|
|
194
|
+
start: startIndex,
|
|
195
|
+
end: endIndex,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Walks forwards/backwards towards the boundary of a given format within an
|
|
201
|
+
* array of format objects. Returns the index of the boundary.
|
|
202
|
+
*
|
|
203
|
+
* @param {Array} formats the formats to search for the given format type.
|
|
204
|
+
* @param {number} initialIndex the starting index from which to walk.
|
|
205
|
+
* @param {Object} targetFormatRef a reference to the format type object being sought.
|
|
206
|
+
* @param {number} formatIndex the index at which we expect the target format object to be.
|
|
207
|
+
* @param {string} direction either 'forwards' or 'backwards' to indicate the direction.
|
|
208
|
+
* @return {number} the index of the boundary of the given format.
|
|
209
|
+
*/
|
|
210
|
+
function walkToBoundary(
|
|
211
|
+
formats,
|
|
212
|
+
initialIndex,
|
|
213
|
+
targetFormatRef,
|
|
214
|
+
formatIndex,
|
|
215
|
+
direction
|
|
216
|
+
) {
|
|
217
|
+
let index = initialIndex;
|
|
218
|
+
|
|
219
|
+
const directions = {
|
|
220
|
+
forwards: 1,
|
|
221
|
+
backwards: -1,
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
const directionIncrement = directions[ direction ] || 1; // invalid direction arg default to forwards
|
|
225
|
+
const inverseDirectionIncrement = directionIncrement * -1;
|
|
226
|
+
|
|
227
|
+
while (
|
|
228
|
+
formats[ index ] &&
|
|
229
|
+
formats[ index ][ formatIndex ] === targetFormatRef
|
|
230
|
+
) {
|
|
231
|
+
// Increment/decrement in the direction of operation.
|
|
232
|
+
index = index + directionIncrement;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Restore by one in inverse direction of operation
|
|
236
|
+
// to avoid out of bounds.
|
|
237
|
+
index = index + inverseDirectionIncrement;
|
|
238
|
+
|
|
239
|
+
return index;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const walkToStart = partialRight( walkToBoundary, 'backwards' );
|
|
243
|
+
|
|
244
|
+
const walkToEnd = partialRight( walkToBoundary, 'forwards' );
|
|
@@ -16,7 +16,7 @@ export const strikethrough = {
|
|
|
16
16
|
className: null,
|
|
17
17
|
edit( { isActive, value, onChange, onFocus } ) {
|
|
18
18
|
function onClick() {
|
|
19
|
-
onChange( toggleFormat( value, { type: name } ) );
|
|
19
|
+
onChange( toggleFormat( value, { type: name, title } ) );
|
|
20
20
|
onFocus();
|
|
21
21
|
}
|
|
22
22
|
|
|
@@ -26,6 +26,7 @@ export const strikethrough = {
|
|
|
26
26
|
title={ title }
|
|
27
27
|
onClick={ onClick }
|
|
28
28
|
isActive={ isActive }
|
|
29
|
+
role="menuitemcheckbox"
|
|
29
30
|
/>
|
|
30
31
|
);
|
|
31
32
|
},
|
package/src/subscript/index.js
CHANGED
|
@@ -16,7 +16,7 @@ export const subscript = {
|
|
|
16
16
|
className: null,
|
|
17
17
|
edit( { isActive, value, onChange, onFocus } ) {
|
|
18
18
|
function onToggle() {
|
|
19
|
-
onChange( toggleFormat( value, { type: name } ) );
|
|
19
|
+
onChange( toggleFormat( value, { type: name, title } ) );
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
function onClick() {
|
|
@@ -30,6 +30,7 @@ export const subscript = {
|
|
|
30
30
|
title={ title }
|
|
31
31
|
onClick={ onClick }
|
|
32
32
|
isActive={ isActive }
|
|
33
|
+
role="menuitemcheckbox"
|
|
33
34
|
/>
|
|
34
35
|
);
|
|
35
36
|
},
|
package/src/superscript/index.js
CHANGED
|
@@ -16,7 +16,7 @@ export const superscript = {
|
|
|
16
16
|
className: null,
|
|
17
17
|
edit( { isActive, value, onChange, onFocus } ) {
|
|
18
18
|
function onToggle() {
|
|
19
|
-
onChange( toggleFormat( value, { type: name } ) );
|
|
19
|
+
onChange( toggleFormat( value, { type: name, title } ) );
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
function onClick() {
|
|
@@ -30,6 +30,7 @@ export const superscript = {
|
|
|
30
30
|
title={ title }
|
|
31
31
|
onClick={ onClick }
|
|
32
32
|
isActive={ isActive }
|
|
33
|
+
role="menuitemcheckbox"
|
|
33
34
|
/>
|
|
34
35
|
);
|
|
35
36
|
},
|
package/src/text-color/index.js
CHANGED
package/src/text-color/inline.js
CHANGED
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
getColorObjectByColorValue,
|
|
21
21
|
getColorObjectByAttributeValues,
|
|
22
22
|
store as blockEditorStore,
|
|
23
|
+
useCachedTruthy,
|
|
23
24
|
} from '@wordpress/block-editor';
|
|
24
25
|
import { Popover, TabPanel } from '@wordpress/components';
|
|
25
26
|
import { __ } from '@wordpress/i18n';
|
|
@@ -139,7 +140,17 @@ export default function InlineColorUI( {
|
|
|
139
140
|
onClose,
|
|
140
141
|
contentRef,
|
|
141
142
|
} ) {
|
|
142
|
-
|
|
143
|
+
/*
|
|
144
|
+
As you change the text color by typing a HEX value into a field,
|
|
145
|
+
the return value of document.getSelection jumps to the field you're editing,
|
|
146
|
+
not the highlighted text. Given that useAnchorRef uses document.getSelection,
|
|
147
|
+
it will return null, since it can't find the <mark> element within the HEX input.
|
|
148
|
+
This caches the last truthy value of the selection anchor reference.
|
|
149
|
+
*/
|
|
150
|
+
const anchorRef = useCachedTruthy(
|
|
151
|
+
useAnchorRef( { ref: contentRef, value, settings } )
|
|
152
|
+
);
|
|
153
|
+
|
|
143
154
|
return (
|
|
144
155
|
<Popover
|
|
145
156
|
onClose={ onClose }
|
package/src/underline/index.js
CHANGED
|
@@ -9,10 +9,11 @@ import {
|
|
|
9
9
|
} from '@wordpress/block-editor';
|
|
10
10
|
|
|
11
11
|
const name = 'core/underline';
|
|
12
|
+
const title = __( 'Underline' );
|
|
12
13
|
|
|
13
14
|
export const underline = {
|
|
14
15
|
name,
|
|
15
|
-
title
|
|
16
|
+
title,
|
|
16
17
|
tagName: 'span',
|
|
17
18
|
className: null,
|
|
18
19
|
attributes: {
|
|
@@ -26,6 +27,7 @@ export const underline = {
|
|
|
26
27
|
attributes: {
|
|
27
28
|
style: 'text-decoration: underline;',
|
|
28
29
|
},
|
|
30
|
+
title,
|
|
29
31
|
} )
|
|
30
32
|
);
|
|
31
33
|
};
|