2022-04-11 14:04:30 +02:00
/******/ ( function ( ) { // webpackBootstrap
/******/ "use strict" ;
/******/ // The require scope
/******/ var _ _webpack _require _ _ = { } ;
/******/
/************************************************************************/
2022-09-20 17:43:29 +02:00
/******/ /* webpack/runtime/compat get default export */
/******/ ! function ( ) {
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ _ _webpack _require _ _ . n = function ( module ) {
/******/ var getter = module && module . _ _esModule ?
/******/ function ( ) { return module [ 'default' ] ; } :
/******/ function ( ) { return module ; } ;
/******/ _ _webpack _require _ _ . d ( getter , { a : getter } ) ;
/******/ return getter ;
/******/ } ;
/******/ } ( ) ;
/******/
2022-04-11 14:04:30 +02:00
/******/ /* webpack/runtime/define property getters */
/******/ ! function ( ) {
/******/ // define getter functions for harmony exports
/******/ _ _webpack _require _ _ . d = function ( exports , definition ) {
/******/ for ( var key in definition ) {
/******/ if ( _ _webpack _require _ _ . o ( definition , key ) && ! _ _webpack _require _ _ . o ( exports , key ) ) {
/******/ Object . defineProperty ( exports , key , { enumerable : true , get : definition [ key ] } ) ;
/******/ }
/******/ }
/******/ } ;
/******/ } ( ) ;
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ ! function ( ) {
/******/ _ _webpack _require _ _ . o = function ( obj , prop ) { return Object . prototype . hasOwnProperty . call ( obj , prop ) ; }
/******/ } ( ) ;
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ ! function ( ) {
/******/ // define __esModule on exports
/******/ _ _webpack _require _ _ . r = function ( exports ) {
/******/ if ( typeof Symbol !== 'undefined' && Symbol . toStringTag ) {
/******/ Object . defineProperty ( exports , Symbol . toStringTag , { value : 'Module' } ) ;
/******/ }
/******/ Object . defineProperty ( exports , '__esModule' , { value : true } ) ;
2018-12-14 05:41:57 +01:00
/******/ } ;
2022-04-11 14:04:30 +02:00
/******/ } ( ) ;
/******/
2018-12-14 05:41:57 +01:00
/************************************************************************/
2022-04-11 14:04:30 +02:00
var _ _webpack _exports _ _ = { } ;
// ESM COMPAT FLAG
_ _webpack _require _ _ . r ( _ _webpack _exports _ _ ) ;
2021-01-28 03:04:13 +01:00
2022-04-11 14:04:30 +02:00
// EXPORTS
_ _webpack _require _ _ . d ( _ _webpack _exports _ _ , {
"__UNSTABLE_LINE_SEPARATOR" : function ( ) { return /* reexport */ LINE _SEPARATOR ; } ,
"__experimentalRichText" : function ( ) { return /* reexport */ _ _experimentalRichText ; } ,
"__unstableCreateElement" : function ( ) { return /* reexport */ createElement ; } ,
"__unstableFormatEdit" : function ( ) { return /* reexport */ FormatEdit ; } ,
"__unstableInsertLineSeparator" : function ( ) { return /* reexport */ insertLineSeparator ; } ,
"__unstableIsEmptyLine" : function ( ) { return /* reexport */ isEmptyLine ; } ,
"__unstableToDom" : function ( ) { return /* reexport */ toDom ; } ,
"__unstableUseRichText" : function ( ) { return /* reexport */ useRichText ; } ,
"applyFormat" : function ( ) { return /* reexport */ applyFormat ; } ,
"concat" : function ( ) { return /* reexport */ concat ; } ,
"create" : function ( ) { return /* reexport */ create ; } ,
"getActiveFormat" : function ( ) { return /* reexport */ getActiveFormat ; } ,
2022-09-20 17:43:29 +02:00
"getActiveFormats" : function ( ) { return /* reexport */ getActiveFormats ; } ,
2022-04-11 14:04:30 +02:00
"getActiveObject" : function ( ) { return /* reexport */ getActiveObject ; } ,
"getTextContent" : function ( ) { return /* reexport */ getTextContent ; } ,
"insert" : function ( ) { return /* reexport */ insert ; } ,
"insertObject" : function ( ) { return /* reexport */ insertObject ; } ,
"isCollapsed" : function ( ) { return /* reexport */ isCollapsed ; } ,
"isEmpty" : function ( ) { return /* reexport */ isEmpty ; } ,
"join" : function ( ) { return /* reexport */ join ; } ,
"registerFormatType" : function ( ) { return /* reexport */ registerFormatType ; } ,
"remove" : function ( ) { return /* reexport */ remove ; } ,
"removeFormat" : function ( ) { return /* reexport */ removeFormat ; } ,
"replace" : function ( ) { return /* reexport */ replace _replace ; } ,
"slice" : function ( ) { return /* reexport */ slice ; } ,
"split" : function ( ) { return /* reexport */ split ; } ,
"store" : function ( ) { return /* reexport */ store ; } ,
"toHTMLString" : function ( ) { return /* reexport */ toHTMLString ; } ,
"toggleFormat" : function ( ) { return /* reexport */ toggleFormat ; } ,
"unregisterFormatType" : function ( ) { return /* reexport */ unregisterFormatType ; } ,
2022-09-20 17:43:29 +02:00
"useAnchor" : function ( ) { return /* reexport */ useAnchor ; } ,
2022-04-11 14:04:30 +02:00
"useAnchorRef" : function ( ) { return /* reexport */ useAnchorRef ; }
} ) ;
2021-01-28 03:04:13 +01:00
2022-04-11 14:04:30 +02:00
// NAMESPACE OBJECT: ./node_modules/@wordpress/rich-text/build-module/store/selectors.js
var selectors _namespaceObject = { } ;
_ _webpack _require _ _ . r ( selectors _namespaceObject ) ;
_ _webpack _require _ _ . d ( selectors _namespaceObject , {
"getFormatType" : function ( ) { return getFormatType ; } ,
"getFormatTypeForBareElement" : function ( ) { return getFormatTypeForBareElement ; } ,
"getFormatTypeForClassName" : function ( ) { return getFormatTypeForClassName ; } ,
"getFormatTypes" : function ( ) { return getFormatTypes ; }
} ) ;
2020-03-24 00:40:19 +01:00
2022-04-11 14:04:30 +02:00
// NAMESPACE OBJECT: ./node_modules/@wordpress/rich-text/build-module/store/actions.js
var actions _namespaceObject = { } ;
_ _webpack _require _ _ . r ( actions _namespaceObject ) ;
_ _webpack _require _ _ . d ( actions _namespaceObject , {
"addFormatTypes" : function ( ) { return addFormatTypes ; } ,
"removeFormatTypes" : function ( ) { return removeFormatTypes ; }
} ) ;
2020-06-26 15:33:47 +02:00
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: external ["wp","data"]
var external _wp _data _namespaceObject = window [ "wp" ] [ "data" ] ;
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/store/reducer.js
/ * *
* WordPress dependencies
* /
2021-11-08 15:29:21 +01:00
2022-04-11 14:04:30 +02:00
/ * *
* Reducer managing the format types
*
* @ param { Object } state Current state .
* @ param { Object } action Dispatched action .
*
* @ return { Object } Updated state .
* /
2021-11-08 15:29:21 +01:00
2023-06-27 16:24:19 +02:00
function formatTypes ( state = { } , action ) {
2022-04-11 14:04:30 +02:00
switch ( action . type ) {
case 'ADD_FORMAT_TYPES' :
return { ... state ,
2022-09-20 17:43:29 +02:00
// Key format types by their name.
... action . formatTypes . reduce ( ( newFormatTypes , type ) => ( { ... newFormatTypes ,
[ type . name ] : type
} ) , { } )
2022-04-11 14:04:30 +02:00
} ;
2021-11-08 15:29:21 +01:00
2022-04-11 14:04:30 +02:00
case 'REMOVE_FORMAT_TYPES' :
2023-06-27 16:24:19 +02:00
return Object . fromEntries ( Object . entries ( state ) . filter ( ( [ key ] ) => ! action . names . includes ( key ) ) ) ;
2022-04-11 14:04:30 +02:00
}
2021-11-08 15:29:21 +01:00
2022-04-11 14:04:30 +02:00
return state ;
}
/* harmony default export */ var reducer = ( ( 0 , external _wp _data _namespaceObject . combineReducers ) ( {
formatTypes
} ) ) ;
2020-06-26 15:33:47 +02:00
2022-09-20 17:43:29 +02:00
; // CONCATENATED MODULE: ./node_modules/rememo/rememo.js
2019-03-07 10:09:59 +01:00
2022-09-20 17:43:29 +02:00
/** @typedef {(...args: any[]) => *[]} GetDependants */
/** @typedef {() => void} Clear */
2019-03-07 10:09:59 +01:00
/ * *
2022-09-20 17:43:29 +02:00
* @ typedef { {
* getDependants : GetDependants ,
* clear : Clear
* } } EnhancedSelector
* /
/ * *
* Internal cache entry .
2020-01-22 23:06:21 +01:00
*
2022-09-20 17:43:29 +02:00
* @ typedef CacheNode
*
* @ property { ? CacheNode | undefined } [ prev ] Previous node .
* @ property { ? CacheNode | undefined } [ next ] Next node .
* @ property { * [ ] } args Function arguments for cache entry .
* @ property { * } val Function result .
* /
/ * *
* @ typedef Cache
*
* @ property { Clear } clear Function to clear cache .
* @ property { boolean } [ isUniqueByDependants ] Whether dependants are valid in
* considering cache uniqueness . A cache is unique if dependents are all arrays
* or objects .
* @ property { CacheNode ? } [ head ] Cache head .
* @ property { * [ ] } [ lastDependants ] Dependants from previous invocation .
2019-03-07 10:09:59 +01:00
* /
/ * *
2022-09-20 17:43:29 +02:00
* Arbitrary value used as key for referencing cache object in WeakMap tree .
2020-01-22 23:06:21 +01:00
*
2022-09-20 17:43:29 +02:00
* @ type { { } }
2019-03-07 10:09:59 +01:00
* /
2022-09-20 17:43:29 +02:00
var LEAF _KEY = { } ;
2019-03-07 10:09:59 +01:00
/ * *
2020-01-22 23:06:21 +01:00
* Returns the first argument as the sole entry in an array .
2019-03-07 10:09:59 +01:00
*
2022-09-20 17:43:29 +02:00
* @ template T
2019-03-07 10:09:59 +01:00
*
2022-09-20 17:43:29 +02:00
* @ param { T } value Value to return .
*
* @ return { [ T ] } Value returned as entry in array .
2019-03-07 10:09:59 +01:00
* /
2022-09-20 17:43:29 +02:00
function arrayOf ( value ) {
return [ value ] ;
2019-03-07 10:09:59 +01:00
}
/ * *
2020-01-22 23:06:21 +01:00
* Returns true if the value passed is object - like , or false otherwise . A value
* is object - like if it can support property assignment , e . g . object or array .
2019-03-07 10:09:59 +01:00
*
2020-01-22 23:06:21 +01:00
* @ param { * } value Value to test .
2019-03-07 10:09:59 +01:00
*
2020-01-22 23:06:21 +01:00
* @ return { boolean } Whether value is object - like .
2019-03-07 10:09:59 +01:00
* /
2022-09-20 17:43:29 +02:00
function isObjectLike ( value ) {
return ! ! value && 'object' === typeof value ;
2020-01-22 23:06:21 +01:00
}
2019-03-07 10:09:59 +01:00
/ * *
2020-01-22 23:06:21 +01:00
* Creates and returns a new cache object .
2019-03-07 10:09:59 +01:00
*
2022-09-20 17:43:29 +02:00
* @ return { Cache } Cache object .
2019-03-07 10:09:59 +01:00
* /
2020-01-22 23:06:21 +01:00
function createCache ( ) {
2022-09-20 17:43:29 +02:00
/** @type {Cache} */
2020-01-22 23:06:21 +01:00
var cache = {
2022-09-20 17:43:29 +02:00
clear : function ( ) {
2020-01-22 23:06:21 +01:00
cache . head = null ;
} ,
} ;
2019-03-07 10:09:59 +01:00
2020-01-22 23:06:21 +01:00
return cache ;
2019-03-07 10:09:59 +01:00
}
/ * *
2020-01-22 23:06:21 +01:00
* Returns true if entries within the two arrays are strictly equal by
* reference from a starting index .
2019-03-07 10:09:59 +01:00
*
2022-09-20 17:43:29 +02:00
* @ param { * [ ] } a First array .
* @ param { * [ ] } b Second array .
2020-01-22 23:06:21 +01:00
* @ param { number } fromIndex Index from which to start comparison .
*
* @ return { boolean } Whether arrays are shallowly equal .
2019-03-07 10:09:59 +01:00
* /
2022-09-20 17:43:29 +02:00
function isShallowEqual ( a , b , fromIndex ) {
2020-01-22 23:06:21 +01:00
var i ;
2019-03-07 10:09:59 +01:00
2022-09-20 17:43:29 +02:00
if ( a . length !== b . length ) {
2020-01-22 23:06:21 +01:00
return false ;
}
2019-03-07 10:09:59 +01:00
2022-09-20 17:43:29 +02:00
for ( i = fromIndex ; i < a . length ; i ++ ) {
if ( a [ i ] !== b [ i ] ) {
2020-01-22 23:06:21 +01:00
return false ;
}
}
2019-03-07 10:09:59 +01:00
2020-01-22 23:06:21 +01:00
return true ;
2019-03-07 10:09:59 +01:00
}
/ * *
2020-01-22 23:06:21 +01:00
* Returns a memoized selector function . The getDependants function argument is
* called before the memoized selector and is expected to return an immutable
* reference or array of references on which the selector depends for computing
* its own return value . The memoize cache is preserved only as long as those
* dependant references remain the same . If getDependants returns a different
* reference ( s ) , the cache is cleared and the selector value regenerated .
2019-03-07 10:09:59 +01:00
*
2022-09-20 17:43:29 +02:00
* @ template { ( ... args : * [ ] ) => * } S
2019-03-07 10:09:59 +01:00
*
2022-09-20 17:43:29 +02:00
* @ param { S } selector Selector function .
* @ param { GetDependants = } getDependants Dependant getter returning an array of
* references used in cache bust consideration .
2019-03-07 10:09:59 +01:00
* /
2022-09-20 17:43:29 +02:00
/* harmony default export */ function rememo ( selector , getDependants ) {
/** @type {WeakMap<*,*>} */
var rootCache ;
2020-01-22 23:06:21 +01:00
2022-09-20 17:43:29 +02:00
/** @type {GetDependants} */
var normalizedGetDependants = getDependants ? getDependants : arrayOf ;
2020-01-22 23:06:21 +01:00
/ * *
* Returns the cache for a given dependants array . When possible , a WeakMap
* will be used to create a unique cache for each set of dependants . This
* is feasible due to the nature of WeakMap in allowing garbage collection
* to occur on entries where the key object is no longer referenced . Since
* WeakMap requires the key to be an object , this is only possible when the
* dependant is object - like . The root cache is created as a hierarchy where
* each top - level key is the first entry in a dependants set , the value a
* WeakMap where each key is the next dependant , and so on . This continues
* so long as the dependants are object - like . If no dependants are object -
* like , then the cache is shared across all invocations .
*
* @ see isObjectLike
*
2022-09-20 17:43:29 +02:00
* @ param { * [ ] } dependants Selector dependants .
2020-01-22 23:06:21 +01:00
*
2022-09-20 17:43:29 +02:00
* @ return { Cache } Cache object .
2020-01-22 23:06:21 +01:00
* /
2022-09-20 17:43:29 +02:00
function getCache ( dependants ) {
2020-01-22 23:06:21 +01:00
var caches = rootCache ,
isUniqueByDependants = true ,
2022-09-20 17:43:29 +02:00
i ,
dependant ,
map ,
cache ;
2020-01-22 23:06:21 +01:00
2022-09-20 17:43:29 +02:00
for ( i = 0 ; i < dependants . length ; i ++ ) {
dependant = dependants [ i ] ;
2020-01-22 23:06:21 +01:00
// Can only compose WeakMap from object-like key.
2022-09-20 17:43:29 +02:00
if ( ! isObjectLike ( dependant ) ) {
2020-01-22 23:06:21 +01:00
isUniqueByDependants = false ;
break ;
}
// Does current segment of cache already have a WeakMap?
2022-09-20 17:43:29 +02:00
if ( caches . has ( dependant ) ) {
2020-01-22 23:06:21 +01:00
// Traverse into nested WeakMap.
2022-09-20 17:43:29 +02:00
caches = caches . get ( dependant ) ;
2020-01-22 23:06:21 +01:00
} else {
// Create, set, and traverse into a new one.
map = new WeakMap ( ) ;
2022-09-20 17:43:29 +02:00
caches . set ( dependant , map ) ;
2020-01-22 23:06:21 +01:00
caches = map ;
}
}
// We use an arbitrary (but consistent) object as key for the last item
// in the WeakMap to serve as our running cache.
2022-09-20 17:43:29 +02:00
if ( ! caches . has ( LEAF _KEY ) ) {
2020-01-22 23:06:21 +01:00
cache = createCache ( ) ;
cache . isUniqueByDependants = isUniqueByDependants ;
2022-09-20 17:43:29 +02:00
caches . set ( LEAF _KEY , cache ) ;
2020-01-22 23:06:21 +01:00
}
2022-09-20 17:43:29 +02:00
return caches . get ( LEAF _KEY ) ;
2020-01-22 23:06:21 +01:00
}
/ * *
* Resets root memoization cache .
* /
function clear ( ) {
2022-09-20 17:43:29 +02:00
rootCache = new WeakMap ( ) ;
2020-01-22 23:06:21 +01:00
}
2022-09-20 17:43:29 +02:00
/* eslint-disable jsdoc/check-param-names */
2020-01-22 23:06:21 +01:00
/ * *
* The augmented selector call , considering first whether dependants have
* changed before passing it to underlying memoize function .
*
2022-09-20 17:43:29 +02:00
* @ param { * } source Source object for derivation .
* @ param { ... * } extraArgs Additional arguments to pass to selector .
2020-01-22 23:06:21 +01:00
*
* @ return { * } Selector result .
* /
2022-09-20 17:43:29 +02:00
/* eslint-enable jsdoc/check-param-names */
function callSelector ( /* source, ...extraArgs */ ) {
2020-01-22 23:06:21 +01:00
var len = arguments . length ,
2022-09-20 17:43:29 +02:00
cache ,
node ,
i ,
args ,
dependants ;
2020-01-22 23:06:21 +01:00
// Create copy of arguments (avoid leaking deoptimization).
2022-09-20 17:43:29 +02:00
args = new Array ( len ) ;
for ( i = 0 ; i < len ; i ++ ) {
args [ i ] = arguments [ i ] ;
2020-01-22 23:06:21 +01:00
}
2022-09-20 17:43:29 +02:00
dependants = normalizedGetDependants . apply ( null , args ) ;
cache = getCache ( dependants ) ;
// If not guaranteed uniqueness by dependants (primitive type), shallow
// compare against last dependants and, if references have changed,
// destroy cache to recalculate result.
if ( ! cache . isUniqueByDependants ) {
if (
cache . lastDependants &&
! isShallowEqual ( dependants , cache . lastDependants , 0 )
) {
2020-01-22 23:06:21 +01:00
cache . clear ( ) ;
}
cache . lastDependants = dependants ;
}
node = cache . head ;
2022-09-20 17:43:29 +02:00
while ( node ) {
2020-01-22 23:06:21 +01:00
// Check whether node arguments match arguments
2022-09-20 17:43:29 +02:00
if ( ! isShallowEqual ( node . args , args , 1 ) ) {
2020-01-22 23:06:21 +01:00
node = node . next ;
continue ;
}
// At this point we can assume we've found a match
// Surface matched node to head if not already
2022-09-20 17:43:29 +02:00
if ( node !== cache . head ) {
2020-01-22 23:06:21 +01:00
// Adjust siblings to point to each other.
2022-09-20 17:43:29 +02:00
/** @type {CacheNode} */ ( node . prev ) . next = node . next ;
if ( node . next ) {
2020-01-22 23:06:21 +01:00
node . next . prev = node . prev ;
}
node . next = cache . head ;
node . prev = null ;
2022-09-20 17:43:29 +02:00
/** @type {CacheNode} */ ( cache . head ) . prev = node ;
2020-01-22 23:06:21 +01:00
cache . head = node ;
}
// Return immediately
return node . val ;
}
// No cached value found. Continue to insertion phase:
2022-09-20 17:43:29 +02:00
node = /** @type {CacheNode} */ ( {
2020-01-22 23:06:21 +01:00
// Generate the result from original function
2022-09-20 17:43:29 +02:00
val : selector . apply ( null , args ) ,
} ) ;
2020-01-22 23:06:21 +01:00
// Avoid including the source object in the cache.
2022-09-20 17:43:29 +02:00
args [ 0 ] = null ;
2020-01-22 23:06:21 +01:00
node . args = args ;
// Don't need to check whether node is already head, since it would
// have been returned above already if it was
// Shift existing head down list
2022-09-20 17:43:29 +02:00
if ( cache . head ) {
2020-01-22 23:06:21 +01:00
cache . head . prev = node ;
node . next = cache . head ;
}
cache . head = node ;
return node . val ;
}
2022-09-20 17:43:29 +02:00
callSelector . getDependants = normalizedGetDependants ;
2020-01-22 23:06:21 +01:00
callSelector . clear = clear ;
clear ( ) ;
2022-09-20 17:43:29 +02:00
return /** @type {S & EnhancedSelector} */ ( callSelector ) ;
2020-01-22 23:06:21 +01:00
}
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/store/selectors.js
2020-01-22 23:06:21 +01:00
/ * *
* External dependencies
* /
/ * *
* Returns all the available format types .
*
* @ param { Object } state Data state .
*
* @ return { Array } Format types .
* /
2022-04-11 14:04:30 +02:00
const getFormatTypes = rememo ( state => Object . values ( state . formatTypes ) , state => [ state . formatTypes ] ) ;
2020-01-22 23:06:21 +01:00
/ * *
* Returns a format type by name .
*
* @ param { Object } state Data state .
2021-11-08 15:29:21 +01:00
* @ param { string } name Format type name .
2020-01-22 23:06:21 +01:00
*
* @ return { Object ? } Format type .
* /
function getFormatType ( state , name ) {
return state . formatTypes [ name ] ;
}
/ * *
* Gets the format type , if any , that can handle a bare element ( without a
* data - format - type attribute ) , given the tag name of this element .
*
* @ param { Object } state Data state .
* @ param { string } bareElementTagName The tag name of the element to find a
* format type for .
* @ return { ? Object } Format type .
* /
function getFormatTypeForBareElement ( state , bareElementTagName ) {
2023-02-07 08:04:52 +01:00
const formatTypes = getFormatTypes ( state ) ;
2023-06-27 16:24:19 +02:00
return formatTypes . find ( ( {
className ,
tagName
} ) => {
2020-01-22 23:06:21 +01:00
return className === null && bareElementTagName === tagName ;
2023-06-27 16:24:19 +02:00
} ) || formatTypes . find ( ( {
className ,
tagName
} ) => {
2023-02-07 08:04:52 +01:00
return className === null && '*' === tagName ;
2020-01-22 23:06:21 +01:00
} ) ;
}
/ * *
* Gets the format type , if any , that can handle an element , given its classes .
*
* @ param { Object } state Data state .
* @ param { string } elementClassName The classes of the element to find a format
* type for .
* @ return { ? Object } Format type .
* /
function getFormatTypeForClassName ( state , elementClassName ) {
2023-06-27 16:24:19 +02:00
return getFormatTypes ( state ) . find ( ( {
className
} ) => {
2020-01-22 23:06:21 +01:00
if ( className === null ) {
return false ;
}
2021-05-19 17:09:27 +02:00
return ` ${ elementClassName } ` . indexOf ( ` ${ className } ` ) >= 0 ;
2020-01-22 23:06:21 +01:00
} ) ;
}
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/store/actions.js
2020-01-22 23:06:21 +01:00
/ * *
* Returns an action object used in signalling that format types have been
* added .
*
* @ param { Array | Object } formatTypes Format types received .
*
* @ return { Object } Action object .
* /
function addFormatTypes ( formatTypes ) {
return {
type : 'ADD_FORMAT_TYPES' ,
2023-02-07 08:04:52 +01:00
formatTypes : Array . isArray ( formatTypes ) ? formatTypes : [ formatTypes ]
2020-01-22 23:06:21 +01:00
} ;
}
/ * *
* Returns an action object used to remove a registered format type .
*
* @ param { string | Array } names Format name .
*
* @ return { Object } Action object .
* /
2019-03-07 10:09:59 +01:00
function removeFormatTypes ( names ) {
2018-12-18 04:14:52 +01:00
return {
type : 'REMOVE_FORMAT_TYPES' ,
2023-02-07 08:04:52 +01:00
names : Array . isArray ( names ) ? names : [ names ]
2018-12-18 04:14:52 +01:00
} ;
}
2018-12-14 05:41:57 +01:00
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/store/index.js
2018-12-14 12:02:53 +01:00
/ * *
2018-12-17 05:52:00 +01:00
* WordPress dependencies
2018-12-14 12:02:53 +01:00
* /
2018-12-14 05:41:57 +01:00
/ * *
* Internal dependencies
* /
2018-12-14 12:02:53 +01:00
2021-05-19 17:09:27 +02:00
const STORE _NAME = 'core/rich-text' ;
2021-01-28 03:04:13 +01:00
/ * *
* Store definition for the rich - text namespace .
*
2021-02-02 06:17:13 +01:00
* @ see https : //github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#createReduxStore
2021-01-28 03:04:13 +01:00
*
* @ type { Object }
* /
2022-04-11 14:04:30 +02:00
const store = ( 0 , external _wp _data _namespaceObject . createReduxStore ) ( STORE _NAME , {
2018-12-18 04:14:52 +01:00
reducer : reducer ,
selectors : selectors _namespaceObject ,
actions : actions _namespaceObject
} ) ;
2022-04-11 14:04:30 +02:00
( 0 , external _wp _data _namespaceObject . register ) ( store ) ;
2018-12-14 12:02:53 +01:00
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/is-format-equal.js
2023-06-27 16:24:19 +02:00
/** @typedef {import('./types').RichTextFormat} RichTextFormat */
2020-10-13 15:10:30 +02:00
2018-12-14 05:41:57 +01:00
/ * *
2018-12-18 04:14:52 +01:00
* Optimised equality check for format objects .
*
2020-10-13 15:10:30 +02:00
* @ param { ? RichTextFormat } format1 Format to compare .
* @ param { ? RichTextFormat } format2 Format to compare .
2018-12-18 04:14:52 +01:00
*
* @ return { boolean } True if formats are equal , false if not .
2018-12-14 05:41:57 +01:00
* /
2018-12-18 04:14:52 +01:00
function isFormatEqual ( format1 , format2 ) {
// Both not defined.
if ( format1 === format2 ) {
return true ;
} // Either not defined.
2018-12-14 05:41:57 +01:00
2018-12-14 12:02:53 +01:00
2018-12-18 04:14:52 +01:00
if ( ! format1 || ! format2 ) {
return false ;
2018-12-14 12:02:53 +01:00
}
2018-12-18 04:14:52 +01:00
if ( format1 . type !== format2 . type ) {
return false ;
}
2018-12-17 05:52:00 +01:00
2021-05-19 17:09:27 +02:00
const attributes1 = format1 . attributes ;
const attributes2 = format2 . attributes ; // Both not defined.
2018-12-17 05:52:00 +01:00
2018-12-18 04:14:52 +01:00
if ( attributes1 === attributes2 ) {
return true ;
} // Either not defined.
2018-12-17 05:52:00 +01:00
2018-12-18 04:14:52 +01:00
if ( ! attributes1 || ! attributes2 ) {
return false ;
2018-12-17 05:52:00 +01:00
}
2018-12-14 12:02:53 +01:00
2021-05-19 17:09:27 +02:00
const keys1 = Object . keys ( attributes1 ) ;
const keys2 = Object . keys ( attributes2 ) ;
2018-12-14 12:02:53 +01:00
2018-12-18 04:14:52 +01:00
if ( keys1 . length !== keys2 . length ) {
return false ;
2018-12-14 12:02:53 +01:00
}
2021-05-19 17:09:27 +02:00
const length = keys1 . length ; // Optimise for speed.
2018-12-14 12:02:53 +01:00
2021-05-19 17:09:27 +02:00
for ( let i = 0 ; i < length ; i ++ ) {
const name = keys1 [ i ] ;
2018-12-14 12:02:53 +01:00
2018-12-18 04:14:52 +01:00
if ( attributes1 [ name ] !== attributes2 [ name ] ) {
return false ;
2018-12-14 12:02:53 +01:00
}
}
2018-12-18 04:14:52 +01:00
return true ;
2018-12-14 12:02:53 +01:00
}
2018-12-18 04:14:52 +01:00
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/normalise-formats.js
2018-12-14 05:41:57 +01:00
/ * *
2018-12-18 04:14:52 +01:00
* Internal dependencies
* /
2023-06-27 16:24:19 +02:00
/** @typedef {import('./types').RichTextValue} RichTextValue */
2020-10-13 15:10:30 +02:00
2018-12-18 04:14:52 +01:00
/ * *
Block Editor: Update packages to bring a selection of bugfixes in.
Props iseulde, kjellr, aduth, 0mirka00, mcsf, nosolosw, gziolo, jasmussen, talldanwp, notnownikki, swissspidy, jorgefilipecosta, noisysocks.
See https://github.com/WordPress/gutenberg/pull/14796.
Fixes #46801.
Built from https://develop.svn.wordpress.org/trunk@45138
git-svn-id: http://core.svn.wordpress.org/trunk@44947 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2019-04-08 08:37:57 +02:00
* Normalises formats : ensures subsequent adjacent equal formats have the same
* reference .
2018-12-14 05:41:57 +01:00
*
2020-10-13 15:10:30 +02:00
* @ param { RichTextValue } value Value to normalise formats of .
2018-12-14 05:41:57 +01:00
*
2020-10-13 15:10:30 +02:00
* @ return { RichTextValue } New value with normalised formats .
2018-12-14 05:41:57 +01:00
* /
2019-03-21 13:48:00 +01:00
function normaliseFormats ( value ) {
2021-05-19 17:09:27 +02:00
const newFormats = value . formats . slice ( ) ;
newFormats . forEach ( ( formatsAtIndex , index ) => {
const formatsAtPreviousIndex = newFormats [ index - 1 ] ;
2018-12-14 05:41:57 +01:00
Block Editor: Update packages to bring a selection of bugfixes in.
Props iseulde, kjellr, aduth, 0mirka00, mcsf, nosolosw, gziolo, jasmussen, talldanwp, notnownikki, swissspidy, jorgefilipecosta, noisysocks.
See https://github.com/WordPress/gutenberg/pull/14796.
Fixes #46801.
Built from https://develop.svn.wordpress.org/trunk@45138
git-svn-id: http://core.svn.wordpress.org/trunk@44947 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2019-04-08 08:37:57 +02:00
if ( formatsAtPreviousIndex ) {
2021-05-19 17:09:27 +02:00
const newFormatsAtIndex = formatsAtIndex . slice ( ) ;
newFormatsAtIndex . forEach ( ( format , formatIndex ) => {
const previousFormat = formatsAtPreviousIndex [ formatIndex ] ;
2018-12-14 05:41:57 +01:00
Block Editor: Update packages to bring a selection of bugfixes in.
Props iseulde, kjellr, aduth, 0mirka00, mcsf, nosolosw, gziolo, jasmussen, talldanwp, notnownikki, swissspidy, jorgefilipecosta, noisysocks.
See https://github.com/WordPress/gutenberg/pull/14796.
Fixes #46801.
Built from https://develop.svn.wordpress.org/trunk@45138
git-svn-id: http://core.svn.wordpress.org/trunk@44947 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2019-04-08 08:37:57 +02:00
if ( isFormatEqual ( format , previousFormat ) ) {
newFormatsAtIndex [ formatIndex ] = previousFormat ;
}
} ) ;
newFormats [ index ] = newFormatsAtIndex ;
}
2018-12-18 04:14:52 +01:00
} ) ;
2021-05-19 17:09:27 +02:00
return { ... value ,
2019-03-21 13:48:00 +01:00
formats : newFormats
2021-05-19 17:09:27 +02:00
} ;
2018-12-18 04:14:52 +01:00
}
2018-12-14 05:41:57 +01:00
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/apply-format.js
2018-12-18 04:14:52 +01:00
/ * *
* Internal dependencies
* /
2018-12-14 05:41:57 +01:00
2023-06-27 16:24:19 +02:00
/** @typedef {import('./types').RichTextValue} RichTextValue */
2020-10-13 15:10:30 +02:00
2023-06-27 16:24:19 +02:00
/** @typedef {import('./types').RichTextFormat} RichTextFormat */
2019-09-19 17:19:18 +02:00
function replace ( array , index , value ) {
array = array . slice ( ) ;
array [ index ] = value ;
return array ;
}
2018-12-14 05:41:57 +01:00
/ * *
2018-12-18 04:14:52 +01:00
* Apply a format object to a Rich Text value from the given ` startIndex ` to the
* given ` endIndex ` . Indices are retrieved from the selection if none are
* provided .
2018-12-14 05:41:57 +01:00
*
2020-10-13 15:10:30 +02:00
* @ param { RichTextValue } value Value to modify .
* @ param { RichTextFormat } format Format to apply .
* @ param { number } [ startIndex ] Start index .
* @ param { number } [ endIndex ] End index .
2018-12-18 04:14:52 +01:00
*
2020-10-13 15:10:30 +02:00
* @ return { RichTextValue } A new value with the format applied .
2018-12-14 05:41:57 +01:00
* /
2019-09-19 17:19:18 +02:00
2023-06-27 16:24:19 +02:00
function applyFormat ( value , format , startIndex = value . start , endIndex = value . end ) {
2021-05-19 17:09:27 +02:00
const {
formats ,
activeFormats
} = value ;
const newFormats = formats . slice ( ) ; // The selection is collapsed.
2018-12-14 05:41:57 +01:00
2018-12-18 04:14:52 +01:00
if ( startIndex === endIndex ) {
2023-06-27 16:24:19 +02:00
const startFormat = newFormats [ startIndex ] ? . find ( ( {
type
} ) => type === format . type ) ; // If the caret is at a format of the same type, expand start and end to
2018-12-18 04:14:52 +01:00
// the edges of the format. This is useful to apply new attributes.
2018-12-14 12:02:53 +01:00
2018-12-18 04:14:52 +01:00
if ( startFormat ) {
2021-05-19 17:09:27 +02:00
const index = newFormats [ startIndex ] . indexOf ( startFormat ) ;
2019-09-19 17:19:18 +02:00
while ( newFormats [ startIndex ] && newFormats [ startIndex ] [ index ] === startFormat ) {
newFormats [ startIndex ] = replace ( newFormats [ startIndex ] , index , format ) ;
2018-12-18 04:14:52 +01:00
startIndex -- ;
2018-12-14 05:41:57 +01:00
}
2018-12-18 04:14:52 +01:00
endIndex ++ ;
2018-12-14 05:41:57 +01:00
2019-09-19 17:19:18 +02:00
while ( newFormats [ endIndex ] && newFormats [ endIndex ] [ index ] === startFormat ) {
newFormats [ endIndex ] = replace ( newFormats [ endIndex ] , index , format ) ;
2018-12-18 04:14:52 +01:00
endIndex ++ ;
2019-05-16 20:08:00 +02:00
}
2018-12-18 04:14:52 +01:00
}
} else {
2019-09-19 17:19:18 +02:00
// Determine the highest position the new format can be inserted at.
2021-05-19 17:09:27 +02:00
let position = + Infinity ;
2019-09-19 17:19:18 +02:00
2021-05-19 17:09:27 +02:00
for ( let index = startIndex ; index < endIndex ; index ++ ) {
if ( newFormats [ index ] ) {
2023-06-27 16:24:19 +02:00
newFormats [ index ] = newFormats [ index ] . filter ( ( {
type
} ) => type !== format . type ) ;
2021-05-19 17:09:27 +02:00
const length = newFormats [ index ] . length ;
2019-09-19 17:19:18 +02:00
if ( length < position ) {
position = length ;
}
} else {
2021-05-19 17:09:27 +02:00
newFormats [ index ] = [ ] ;
2019-09-19 17:19:18 +02:00
position = 0 ;
}
}
2021-05-19 17:09:27 +02:00
for ( let index = startIndex ; index < endIndex ; index ++ ) {
newFormats [ index ] . splice ( position , 0 , format ) ;
2018-12-14 05:41:57 +01:00
}
}
2021-05-19 17:09:27 +02:00
return normaliseFormats ( { ... value ,
2019-05-16 20:08:00 +02:00
formats : newFormats ,
// Always revise active formats. This serves as a placeholder for new
// inputs with the format so new input appears with the format applied,
// and ensures a format of the same type uses the latest values.
2023-06-27 16:24:19 +02:00
activeFormats : [ ... ( activeFormats ? . filter ( ( {
type
} ) => type !== format . type ) || [ ] ) , format ]
2021-05-19 17:09:27 +02:00
} ) ;
2018-12-14 05:41:57 +01:00
}
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/create-element.js
2018-12-15 12:00:40 +01:00
/ * *
2018-12-18 04:14:52 +01:00
* Parse the given HTML into a body element .
2018-12-15 12:00:40 +01:00
*
2018-12-19 04:16:48 +01:00
* Note : The current implementation will return a shared reference , reset on
* each call to ` createElement ` . Therefore , you should not hold a reference to
* the value to operate upon asynchronously , as it may have unexpected results .
*
2018-12-18 04:14:52 +01:00
* @ param { HTMLDocument } document The HTML document to use to parse .
* @ param { string } html The HTML to parse .
2018-12-15 12:00:40 +01:00
*
2018-12-18 04:14:52 +01:00
* @ return { HTMLBodyElement } Body element with parsed HTML .
2018-12-15 12:00:40 +01:00
* /
2023-06-27 16:24:19 +02:00
function createElement ( {
implementation
} , html ) {
2018-12-19 04:16:48 +01:00
// Because `createHTMLDocument` is an expensive operation, and with this
// function being internal to `rich-text` (full control in avoiding a risk
// of asynchronous operations on the shared reference), a single document
// is reused and reset for each call to the function.
if ( ! createElement . body ) {
createElement . body = implementation . createHTMLDocument ( '' ) . body ;
}
2018-12-18 04:14:52 +01:00
2018-12-19 04:16:48 +01:00
createElement . body . innerHTML = html ;
return createElement . body ;
2018-12-15 12:00:40 +01:00
}
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/special-characters.js
2019-03-21 13:48:00 +01:00
/ * *
2019-09-19 17:19:18 +02:00
* Line separator character , used for multiline text .
2019-03-21 13:48:00 +01:00
* /
2021-05-19 17:09:27 +02:00
const LINE _SEPARATOR = '\u2028' ;
2019-09-19 17:19:18 +02:00
/ * *
* Object replacement character , used as a placeholder for objects .
* /
2021-05-19 17:09:27 +02:00
const OBJECT _REPLACEMENT _CHARACTER = '\ufffc' ;
2019-09-19 17:19:18 +02:00
/ * *
* Zero width non - breaking space , used as padding in the editable DOM tree when
* it is empty otherwise .
* /
2021-05-19 17:09:27 +02:00
const ZWNBSP = '\ufeff' ;
2019-03-21 13:48:00 +01:00
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/create.js
2018-12-15 12:00:40 +01:00
/ * *
2018-12-18 04:14:52 +01:00
* WordPress dependencies
2018-12-15 12:00:40 +01:00
* /
2018-12-14 05:41:57 +01:00
/ * *
2018-12-18 04:14:52 +01:00
* Internal dependencies
2018-12-14 05:41:57 +01:00
* /
2018-12-14 12:02:53 +01:00
2023-06-27 16:24:19 +02:00
/** @typedef {import('./types').RichTextValue} RichTextValue */
2018-12-14 12:02:53 +01:00
2018-12-18 04:14:52 +01:00
function createEmptyValue ( ) {
return {
formats : [ ] ,
2019-03-21 13:48:00 +01:00
replacements : [ ] ,
2018-12-18 04:14:52 +01:00
text : ''
} ;
}
2018-12-14 12:02:53 +01:00
2023-06-27 16:24:19 +02:00
function toFormat ( {
tagName ,
attributes
} ) {
2021-05-19 17:09:27 +02:00
let formatType ;
2018-12-15 12:00:40 +01:00
2018-12-18 04:14:52 +01:00
if ( attributes && attributes . class ) {
2022-04-11 14:04:30 +02:00
formatType = ( 0 , external _wp _data _namespaceObject . select ) ( store ) . getFormatTypeForClassName ( attributes . class ) ;
2018-12-15 12:00:40 +01:00
2018-12-18 04:14:52 +01:00
if ( formatType ) {
// Preserve any additional classes.
2021-05-19 17:09:27 +02:00
attributes . class = ` ${ attributes . class } ` . replace ( ` ${ formatType . className } ` , ' ' ) . trim ( ) ;
2018-12-15 12:00:40 +01:00
2018-12-18 04:14:52 +01:00
if ( ! attributes . class ) {
delete attributes . class ;
}
}
}
2018-12-15 12:00:40 +01:00
2018-12-18 04:14:52 +01:00
if ( ! formatType ) {
2023-02-07 08:04:52 +01:00
formatType = ( 0 , external _wp _data _namespaceObject . select ) ( store ) . getFormatTypeForBareElement ( tagName ) ;
2018-12-18 04:14:52 +01:00
}
2018-12-15 12:00:40 +01:00
2018-12-18 04:14:52 +01:00
if ( ! formatType ) {
return attributes ? {
2023-02-07 08:04:52 +01:00
type : tagName ,
2021-05-19 17:09:27 +02:00
attributes
2018-12-18 04:14:52 +01:00
} : {
2023-02-07 08:04:52 +01:00
type : tagName
2018-12-18 04:14:52 +01:00
} ;
}
2018-12-15 12:00:40 +01:00
2019-03-21 13:48:00 +01:00
if ( formatType . _ _experimentalCreatePrepareEditableTree && ! formatType . _ _experimentalCreateOnChangeEditableValue ) {
return null ;
}
2018-12-18 04:14:52 +01:00
if ( ! attributes ) {
return {
2023-06-27 16:24:19 +02:00
formatType ,
2023-02-07 08:04:52 +01:00
type : formatType . name ,
tagName
2018-12-18 04:14:52 +01:00
} ;
}
2018-12-15 12:00:40 +01:00
2021-05-19 17:09:27 +02:00
const registeredAttributes = { } ;
const unregisteredAttributes = { } ;
2021-11-08 15:29:21 +01:00
const _attributes = { ... attributes
} ;
2018-12-15 12:00:40 +01:00
2021-11-08 15:29:21 +01:00
for ( const key in formatType . attributes ) {
const name = formatType . attributes [ key ] ;
registeredAttributes [ key ] = _attributes [ name ] ;
2018-12-14 05:41:57 +01:00
2021-11-08 15:29:21 +01:00
if ( formatType . _ _unstableFilterAttributeValue ) {
registeredAttributes [ key ] = formatType . _ _unstableFilterAttributeValue ( key , registeredAttributes [ key ] ) ;
} // delete the attribute and what's left is considered
// to be unregistered.
delete _attributes [ name ] ;
if ( typeof registeredAttributes [ key ] === 'undefined' ) {
delete registeredAttributes [ key ] ;
2018-12-18 04:14:52 +01:00
}
}
2018-12-14 05:41:57 +01:00
2021-11-08 15:29:21 +01:00
for ( const name in _attributes ) {
unregisteredAttributes [ name ] = attributes [ name ] ;
}
2023-06-27 16:24:19 +02:00
if ( formatType . contentEditable === false ) {
delete unregisteredAttributes . contenteditable ;
}
2018-12-18 04:14:52 +01:00
return {
2023-06-27 16:24:19 +02:00
formatType ,
2018-12-18 04:14:52 +01:00
type : formatType . name ,
2023-02-07 08:04:52 +01:00
tagName ,
2018-12-18 04:14:52 +01:00
attributes : registeredAttributes ,
2021-05-19 17:09:27 +02:00
unregisteredAttributes
2018-12-18 04:14:52 +01:00
} ;
}
/ * *
* Create a RichText value from an ` Element ` tree ( DOM ) , an HTML string or a
* plain text string , with optionally a ` Range ` object to set the selection . If
* called without any input , an empty value will be created . If
* ` multilineTag ` is provided , any content of direct children whose type matches
* ` multilineTag ` will be separated by two newlines . The optional functions can
* be used to filter out content .
*
2019-03-21 13:48:00 +01:00
* A value will have the following shape , which you are strongly encouraged not
* to modify without the use of helper functions :
*
* ` ` ` js
* {
* text : string ,
* formats : Array ,
* replacements : Array ,
* ? start : number ,
* ? end : number ,
* }
* ` ` `
*
* As you can see , text and formatting are separated . ` text ` holds the text ,
* including any replacement characters for objects and lines . ` formats ` ,
* ` objects ` and ` lines ` are all sparse arrays of the same length as ` text ` . It
* holds information about the formatting at the relevant text indices . Finally
* ` start ` and ` end ` state which text indices are selected . They are only
* provided if a ` Range ` was given .
*
2021-11-08 15:29:21 +01:00
* @ param { Object } [ $1 ] Optional named arguments .
* @ param { Element } [ $1 . element ] Element to create value from .
* @ param { string } [ $1 . text ] Text to create value from .
* @ param { string } [ $1 . html ] HTML to create value from .
* @ param { Range } [ $1 . range ] Range to create value from .
* @ param { string } [ $1 . multilineTag ] Multiline tag if the structure is
* multiline .
* @ param { Array } [ $1 . multilineWrapperTags ] Tags where lines can be found if
* nesting is possible .
* @ param { boolean } [ $1 . preserveWhiteSpace ] Whether or not to collapse white
* space characters .
2020-10-13 15:10:30 +02:00
* @ param { boolean } [ $1 . _ _unstableIsEditableTree ]
2018-12-18 04:14:52 +01:00
*
2020-10-13 15:10:30 +02:00
* @ return { RichTextValue } A rich text value .
2018-12-18 04:14:52 +01:00
* /
2018-12-14 05:41:57 +01:00
2023-06-27 16:24:19 +02:00
function create ( {
element ,
text ,
html ,
range ,
multilineTag ,
multilineWrapperTags ,
_ _unstableIsEditableTree : isEditableTree ,
preserveWhiteSpace
} = { } ) {
2018-12-18 04:14:52 +01:00
if ( typeof text === 'string' && text . length > 0 ) {
return {
formats : Array ( text . length ) ,
2019-03-21 13:48:00 +01:00
replacements : Array ( text . length ) ,
2021-05-19 17:09:27 +02:00
text
2018-12-18 04:14:52 +01:00
} ;
}
2018-12-14 05:41:57 +01:00
2018-12-18 04:14:52 +01:00
if ( typeof html === 'string' && html . length > 0 ) {
2020-06-26 15:33:47 +02:00
// It does not matter which document this is, we're just using it to
// parse.
2018-12-18 04:14:52 +01:00
element = createElement ( document , html ) ;
}
2018-12-14 05:41:57 +01:00
2021-05-19 17:09:27 +02:00
if ( typeof element !== 'object' ) {
2018-12-18 04:14:52 +01:00
return createEmptyValue ( ) ;
}
2018-12-14 05:41:57 +01:00
2018-12-18 04:14:52 +01:00
if ( ! multilineTag ) {
return createFromElement ( {
2021-05-19 17:09:27 +02:00
element ,
range ,
isEditableTree ,
preserveWhiteSpace
2018-12-18 04:14:52 +01:00
} ) ;
}
2018-12-14 05:41:57 +01:00
2018-12-18 04:14:52 +01:00
return createFromMultilineElement ( {
2021-05-19 17:09:27 +02:00
element ,
range ,
multilineTag ,
multilineWrapperTags ,
isEditableTree ,
preserveWhiteSpace
2018-12-18 04:14:52 +01:00
} ) ;
}
/ * *
* Helper to accumulate the value ' s selection start and end from the current
* node and range .
*
* @ param { Object } accumulator Object to accumulate into .
* @ param { Node } node Node to create value with .
* @ param { Range } range Range to create value with .
* @ param { Object } value Value that is being accumulated .
* /
2018-12-14 12:02:53 +01:00
2018-12-18 04:14:52 +01:00
function accumulateSelection ( accumulator , node , range , value ) {
if ( ! range ) {
return ;
}
2018-12-14 12:02:53 +01:00
2021-05-19 17:09:27 +02:00
const {
parentNode
} = node ;
const {
startContainer ,
startOffset ,
endContainer ,
endOffset
} = range ;
const currentLength = accumulator . text . length ; // Selection can be extracted from value.
2018-12-14 12:02:53 +01:00
2018-12-18 04:14:52 +01:00
if ( value . start !== undefined ) {
accumulator . start = currentLength + value . start ; // Range indicates that the current node has selection.
2020-06-26 15:33:47 +02:00
} else if ( node === startContainer && node . nodeType === node . TEXT _NODE ) {
2018-12-18 04:14:52 +01:00
accumulator . start = currentLength + startOffset ; // Range indicates that the current node is selected.
} else if ( parentNode === startContainer && node === startContainer . childNodes [ startOffset ] ) {
accumulator . start = currentLength ; // Range indicates that the selection is after the current node.
} else if ( parentNode === startContainer && node === startContainer . childNodes [ startOffset - 1 ] ) {
accumulator . start = currentLength + value . text . length ; // Fallback if no child inside handled the selection.
} else if ( node === startContainer ) {
accumulator . start = currentLength ;
} // Selection can be extracted from value.
2018-12-14 12:02:53 +01:00
2018-12-18 04:14:52 +01:00
if ( value . end !== undefined ) {
accumulator . end = currentLength + value . end ; // Range indicates that the current node has selection.
2020-06-26 15:33:47 +02:00
} else if ( node === endContainer && node . nodeType === node . TEXT _NODE ) {
2018-12-18 04:14:52 +01:00
accumulator . end = currentLength + endOffset ; // Range indicates that the current node is selected.
} else if ( parentNode === endContainer && node === endContainer . childNodes [ endOffset - 1 ] ) {
accumulator . end = currentLength + value . text . length ; // Range indicates that the selection is before the current node.
} else if ( parentNode === endContainer && node === endContainer . childNodes [ endOffset ] ) {
accumulator . end = currentLength ; // Fallback if no child inside handled the selection.
} else if ( node === endContainer ) {
accumulator . end = currentLength + endOffset ;
}
}
/ * *
* Adjusts the start and end offsets from a range based on a text filter .
*
* @ param { Node } node Node of which the text should be filtered .
* @ param { Range } range The range to filter .
* @ param { Function } filter Function to use to filter the text .
*
2020-10-13 15:10:30 +02:00
* @ return { Object | void } Object containing range properties .
2018-12-18 04:14:52 +01:00
* /
2018-12-14 12:02:53 +01:00
2018-12-14 05:41:57 +01:00
2018-12-18 04:14:52 +01:00
function filterRange ( node , range , filter ) {
if ( ! range ) {
return ;
}
2018-12-14 05:41:57 +01:00
2021-05-19 17:09:27 +02:00
const {
startContainer ,
endContainer
} = range ;
let {
startOffset ,
endOffset
} = range ;
2018-12-14 05:41:57 +01:00
2018-12-18 04:14:52 +01:00
if ( node === startContainer ) {
startOffset = filter ( node . nodeValue . slice ( 0 , startOffset ) ) . length ;
}
2018-12-14 05:41:57 +01:00
2018-12-18 04:14:52 +01:00
if ( node === endContainer ) {
endOffset = filter ( node . nodeValue . slice ( 0 , endOffset ) ) . length ;
}
2018-12-14 05:41:57 +01:00
2018-12-18 04:14:52 +01:00
return {
2021-05-19 17:09:27 +02:00
startContainer ,
startOffset ,
endContainer ,
endOffset
2018-12-18 04:14:52 +01:00
} ;
}
2020-01-08 12:57:23 +01:00
/ * *
* Collapse any whitespace used for HTML formatting to one space character ,
* because it will also be displayed as such by the browser .
*
* @ param { string } string
* /
function collapseWhiteSpace ( string ) {
return string . replace ( /[\n\r\t]+/g , ' ' ) ;
}
/ * *
2021-11-08 15:29:21 +01:00
* Removes reserved characters used by rich - text ( zero width non breaking spaces added by ` toTree ` and object replacement characters ) .
2020-01-08 12:57:23 +01:00
*
* @ param { string } string
* /
2019-09-19 17:19:18 +02:00
2021-11-08 15:29:21 +01:00
function removeReservedCharacters ( string ) {
2022-04-12 17:12:47 +02:00
// with the global flag, note that we should create a new regex each time OR reset lastIndex state.
2021-11-08 15:29:21 +01:00
return string . replace ( new RegExp ( ` [ ${ ZWNBSP } ${ OBJECT _REPLACEMENT _CHARACTER } ] ` , 'gu' ) , '' ) ;
2019-03-07 10:09:59 +01:00
}
2018-12-18 04:14:52 +01:00
/ * *
* Creates a Rich Text value from a DOM element and range .
*
2020-10-13 15:10:30 +02:00
* @ param { Object } $1 Named argements .
* @ param { Element } [ $1 . element ] Element to create value from .
* @ param { Range } [ $1 . range ] Range to create value from .
* @ param { string } [ $1 . multilineTag ] Multiline tag if the structure is
2018-12-18 04:14:52 +01:00
* multiline .
2020-10-13 15:10:30 +02:00
* @ param { Array } [ $1 . multilineWrapperTags ] Tags where lines can be found if
2018-12-18 04:14:52 +01:00
* nesting is possible .
2020-10-13 15:10:30 +02:00
* @ param { boolean } [ $1 . preserveWhiteSpace ] Whether or not to collapse white
2020-01-08 12:57:23 +01:00
* space characters .
2020-10-13 15:10:30 +02:00
* @ param { Array } [ $1 . currentWrapperTags ]
* @ param { boolean } [ $1 . isEditableTree ]
2018-12-18 04:14:52 +01:00
*
2020-10-13 15:10:30 +02:00
* @ return { RichTextValue } A rich text value .
2018-12-18 04:14:52 +01:00
* /
2018-12-14 05:41:57 +01:00
2023-06-27 16:24:19 +02:00
function createFromElement ( {
element ,
range ,
multilineTag ,
multilineWrapperTags ,
currentWrapperTags = [ ] ,
isEditableTree ,
preserveWhiteSpace
} ) {
2021-05-19 17:09:27 +02:00
const accumulator = createEmptyValue ( ) ;
2018-12-14 05:41:57 +01:00
2018-12-18 04:14:52 +01:00
if ( ! element ) {
return accumulator ;
}
2018-12-14 05:41:57 +01:00
2018-12-18 04:14:52 +01:00
if ( ! element . hasChildNodes ( ) ) {
accumulateSelection ( accumulator , element , range , createEmptyValue ( ) ) ;
return accumulator ;
}
2018-12-14 05:41:57 +01:00
2021-05-19 17:09:27 +02:00
const length = element . childNodes . length ; // Optimise for speed.
2018-12-14 05:41:57 +01:00
2021-05-19 17:09:27 +02:00
for ( let index = 0 ; index < length ; index ++ ) {
const node = element . childNodes [ index ] ;
2023-02-07 08:04:52 +01:00
const tagName = node . nodeName . toLowerCase ( ) ;
2018-12-14 05:41:57 +01:00
2020-06-26 15:33:47 +02:00
if ( node . nodeType === node . TEXT _NODE ) {
2021-11-08 15:29:21 +01:00
let filter = removeReservedCharacters ;
2020-01-08 12:57:23 +01:00
if ( ! preserveWhiteSpace ) {
2021-11-08 15:29:21 +01:00
filter = string => removeReservedCharacters ( collapseWhiteSpace ( string ) ) ;
2020-01-08 12:57:23 +01:00
}
2021-05-19 17:09:27 +02:00
const text = filter ( node . nodeValue ) ;
2020-01-08 12:57:23 +01:00
range = filterRange ( node , range , filter ) ;
2018-12-18 04:14:52 +01:00
accumulateSelection ( accumulator , node , range , {
2021-05-19 17:09:27 +02:00
text
2019-03-21 13:48:00 +01:00
} ) ; // Create a sparse array of the same length as `text`, in which
2018-12-18 04:14:52 +01:00
// formats can be added.
2018-12-14 05:41:57 +01:00
2019-03-21 13:48:00 +01:00
accumulator . formats . length += text . length ;
accumulator . replacements . length += text . length ;
accumulator . text += text ;
2021-05-19 17:09:27 +02:00
continue ;
2018-12-18 04:14:52 +01:00
}
2018-12-14 05:41:57 +01:00
2020-06-26 15:33:47 +02:00
if ( node . nodeType !== node . ELEMENT _NODE ) {
2021-05-19 17:09:27 +02:00
continue ;
2018-12-18 04:14:52 +01:00
}
2018-12-14 05:41:57 +01:00
2019-09-19 17:19:18 +02:00
if ( isEditableTree && ( // Ignore any placeholders.
node . getAttribute ( 'data-rich-text-placeholder' ) || // Ignore any line breaks that are not inserted by us.
2023-02-07 08:04:52 +01:00
tagName === 'br' && ! node . getAttribute ( 'data-rich-text-line-break' ) ) ) {
2018-12-18 04:14:52 +01:00
accumulateSelection ( accumulator , node , range , createEmptyValue ( ) ) ;
2021-05-19 17:09:27 +02:00
continue ;
2018-12-18 04:14:52 +01:00
}
2018-12-14 05:41:57 +01:00
2023-02-07 08:04:52 +01:00
if ( tagName === 'script' ) {
2021-07-14 01:58:30 +02:00
const value = {
formats : [ , ] ,
replacements : [ {
2023-02-07 08:04:52 +01:00
type : tagName ,
2021-07-14 01:58:30 +02:00
attributes : {
'data-rich-text-script' : node . getAttribute ( 'data-rich-text-script' ) || encodeURIComponent ( node . innerHTML )
}
} ] ,
text : OBJECT _REPLACEMENT _CHARACTER
} ;
accumulateSelection ( accumulator , node , range , value ) ;
mergePair ( accumulator , value ) ;
continue ;
}
2023-02-07 08:04:52 +01:00
if ( tagName === 'br' ) {
2018-12-18 04:14:52 +01:00
accumulateSelection ( accumulator , node , range , createEmptyValue ( ) ) ;
2019-03-21 13:48:00 +01:00
mergePair ( accumulator , create ( {
text : '\n'
} ) ) ;
2021-05-19 17:09:27 +02:00
continue ;
2018-12-18 04:14:52 +01:00
}
2018-12-14 05:41:57 +01:00
2021-11-08 15:29:21 +01:00
const format = toFormat ( {
2023-02-07 08:04:52 +01:00
tagName ,
2019-03-07 10:09:59 +01:00
attributes : getAttributes ( {
element : node
} )
2023-06-27 16:24:19 +02:00
} ) ; // When a format type is declared as not editable, replace it with an
// object replacement character and preserve the inner HTML.
if ( format ? . formatType ? . contentEditable === false ) {
delete format . formatType ;
accumulateSelection ( accumulator , node , range , createEmptyValue ( ) ) ;
mergePair ( accumulator , {
formats : [ , ] ,
replacements : [ { ... format ,
innerHTML : node . innerHTML
} ] ,
text : OBJECT _REPLACEMENT _CHARACTER
} ) ;
continue ;
}
if ( format ) delete format . formatType ;
2019-03-07 10:09:59 +01:00
2023-02-07 08:04:52 +01:00
if ( multilineWrapperTags && multilineWrapperTags . indexOf ( tagName ) !== - 1 ) {
2021-05-19 17:09:27 +02:00
const value = createFromMultilineElement ( {
2018-12-18 04:14:52 +01:00
element : node ,
2021-05-19 17:09:27 +02:00
range ,
multilineTag ,
multilineWrapperTags ,
currentWrapperTags : [ ... currentWrapperTags , format ] ,
isEditableTree ,
preserveWhiteSpace
2018-12-18 04:14:52 +01:00
} ) ;
2021-05-19 17:09:27 +02:00
accumulateSelection ( accumulator , node , range , value ) ;
mergePair ( accumulator , value ) ;
continue ;
2018-12-18 04:14:52 +01:00
}
2018-12-15 12:00:40 +01:00
2021-05-19 17:09:27 +02:00
const value = createFromElement ( {
2019-03-21 13:48:00 +01:00
element : node ,
2021-05-19 17:09:27 +02:00
range ,
multilineTag ,
multilineWrapperTags ,
isEditableTree ,
preserveWhiteSpace
2019-03-21 13:48:00 +01:00
} ) ;
accumulateSelection ( accumulator , node , range , value ) ;
2018-12-15 12:00:40 +01:00
2019-03-21 13:48:00 +01:00
if ( ! format ) {
mergePair ( accumulator , value ) ;
} else if ( value . text . length === 0 ) {
if ( format . attributes ) {
mergePair ( accumulator , {
formats : [ , ] ,
replacements : [ format ] ,
text : OBJECT _REPLACEMENT _CHARACTER
} ) ;
2018-12-18 04:14:52 +01:00
}
} else {
2020-01-22 23:06:21 +01:00
// Indices should share a reference to the same formats array.
// Only create a new reference if `formats` changes.
2020-02-06 22:03:31 +01:00
function mergeFormats ( formats ) {
2020-01-22 23:06:21 +01:00
if ( mergeFormats . formats === formats ) {
return mergeFormats . newFormats ;
}
2021-05-19 17:09:27 +02:00
const newFormats = formats ? [ format , ... formats ] : [ format ] ;
2020-01-22 23:06:21 +01:00
mergeFormats . formats = formats ;
mergeFormats . newFormats = newFormats ;
return newFormats ;
2020-02-06 22:03:31 +01:00
} // Since the formats parameter can be `undefined`, preset
2020-01-22 23:06:21 +01:00
// `mergeFormats` with a new reference.
mergeFormats . newFormats = [ format ] ;
2021-05-19 17:09:27 +02:00
mergePair ( accumulator , { ... value ,
2020-01-22 23:06:21 +01:00
formats : Array . from ( value . formats , mergeFormats )
2021-05-19 17:09:27 +02:00
} ) ;
2019-03-21 13:48:00 +01:00
}
2018-12-15 12:00:40 +01:00
}
2018-12-18 04:14:52 +01:00
return accumulator ;
2018-12-15 12:00:40 +01:00
}
2018-12-14 12:02:53 +01:00
/ * *
2018-12-18 04:14:52 +01:00
* Creates a rich text value from a DOM element and range that should be
* multiline .
2018-12-14 12:02:53 +01:00
*
2020-10-13 15:10:30 +02:00
* @ param { Object } $1 Named argements .
* @ param { Element } [ $1 . element ] Element to create value from .
* @ param { Range } [ $1 . range ] Range to create value from .
* @ param { string } [ $1 . multilineTag ] Multiline tag if the structure is
* multiline .
* @ param { Array } [ $1 . multilineWrapperTags ] Tags where lines can be found if
* nesting is possible .
2021-11-08 15:29:21 +01:00
* @ param { Array } [ $1 . currentWrapperTags ] Whether to prepend a line
2020-10-13 15:10:30 +02:00
* separator .
* @ param { boolean } [ $1 . preserveWhiteSpace ] Whether or not to collapse white
* space characters .
* @ param { boolean } [ $1 . isEditableTree ]
2018-12-14 12:02:53 +01:00
*
2020-10-13 15:10:30 +02:00
* @ return { RichTextValue } A rich text value .
2018-12-14 12:02:53 +01:00
* /
2018-12-14 05:41:57 +01:00
2023-06-27 16:24:19 +02:00
function createFromMultilineElement ( {
element ,
range ,
multilineTag ,
multilineWrapperTags ,
currentWrapperTags = [ ] ,
isEditableTree ,
preserveWhiteSpace
} ) {
2021-05-19 17:09:27 +02:00
const accumulator = createEmptyValue ( ) ;
2018-12-14 05:41:57 +01:00
2018-12-18 04:14:52 +01:00
if ( ! element || ! element . hasChildNodes ( ) ) {
return accumulator ;
}
2018-12-14 05:41:57 +01:00
2021-05-19 17:09:27 +02:00
const length = element . children . length ; // Optimise for speed.
2018-12-14 05:41:57 +01:00
2021-05-19 17:09:27 +02:00
for ( let index = 0 ; index < length ; index ++ ) {
const node = element . children [ index ] ;
2018-12-14 05:41:57 +01:00
2018-12-18 04:14:52 +01:00
if ( node . nodeName . toLowerCase ( ) !== multilineTag ) {
continue ;
}
2018-12-14 05:41:57 +01:00
2021-05-19 17:09:27 +02:00
const value = createFromElement ( {
2018-12-18 04:14:52 +01:00
element : node ,
2021-05-19 17:09:27 +02:00
range ,
multilineTag ,
multilineWrapperTags ,
currentWrapperTags ,
isEditableTree ,
preserveWhiteSpace
2019-03-21 13:48:00 +01:00
} ) ; // Multiline value text should be separated by a line separator.
2018-12-14 05:41:57 +01:00
2018-12-18 04:14:52 +01:00
if ( index !== 0 || currentWrapperTags . length > 0 ) {
2019-03-21 13:48:00 +01:00
mergePair ( accumulator , {
formats : [ , ] ,
replacements : currentWrapperTags . length > 0 ? [ currentWrapperTags ] : [ , ] ,
text : LINE _SEPARATOR
} ) ;
2018-12-18 04:14:52 +01:00
}
2018-12-14 05:41:57 +01:00
2018-12-18 04:14:52 +01:00
accumulateSelection ( accumulator , node , range , value ) ;
2019-03-21 13:48:00 +01:00
mergePair ( accumulator , value ) ;
2018-12-18 04:14:52 +01:00
}
2018-12-14 05:41:57 +01:00
2018-12-18 04:14:52 +01:00
return accumulator ;
}
2018-12-14 05:41:57 +01:00
/ * *
2018-12-18 04:14:52 +01:00
* Gets the attributes of an element in object shape .
2018-12-14 05:41:57 +01:00
*
2020-10-13 15:10:30 +02:00
* @ param { Object } $1 Named argements .
* @ param { Element } $1 . element Element to get attributes from .
2018-12-14 05:41:57 +01:00
*
2020-10-13 15:10:30 +02:00
* @ return { Object | void } Attribute object or ` undefined ` if the element has no
* attributes .
2018-12-14 05:41:57 +01:00
* /
2018-12-18 04:14:52 +01:00
2023-06-27 16:24:19 +02:00
function getAttributes ( {
element
} ) {
2018-12-18 04:14:52 +01:00
if ( ! element . hasAttributes ( ) ) {
2018-12-14 05:41:57 +01:00
return ;
}
2021-05-19 17:09:27 +02:00
const length = element . attributes . length ;
let accumulator ; // Optimise for speed.
2018-12-14 05:41:57 +01:00
2021-05-19 17:09:27 +02:00
for ( let i = 0 ; i < length ; i ++ ) {
const {
name ,
value
} = element . attributes [ i ] ;
2018-12-14 05:41:57 +01:00
2019-03-21 13:48:00 +01:00
if ( name . indexOf ( 'data-rich-text-' ) === 0 ) {
2018-12-18 04:14:52 +01:00
continue ;
}
2018-12-14 05:41:57 +01:00
2021-07-14 01:58:30 +02:00
const safeName = /^on/i . test ( name ) ? 'data-disable-rich-text-' + name : name ;
2018-12-18 04:14:52 +01:00
accumulator = accumulator || { } ;
2021-07-14 01:58:30 +02:00
accumulator [ safeName ] = value ;
2018-12-18 04:14:52 +01:00
}
2018-12-14 05:41:57 +01:00
2019-03-07 10:09:59 +01:00
return accumulator ;
}
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/concat.js
2019-03-21 13:48:00 +01:00
/ * *
* Internal dependencies
* /
2023-06-27 16:24:19 +02:00
/** @typedef {import('./types').RichTextValue} RichTextValue */
2020-10-13 15:10:30 +02:00
2019-03-21 13:48:00 +01:00
/ * *
* Concats a pair of rich text values . Not that this mutates ` a ` and does NOT
* normalise formats !
*
2020-10-13 15:10:30 +02:00
* @ param { Object } a Value to mutate .
* @ param { Object } b Value to add read from .
2019-03-21 13:48:00 +01:00
*
* @ return { Object } ` a ` , mutated .
* /
function mergePair ( a , b ) {
a . formats = a . formats . concat ( b . formats ) ;
a . replacements = a . replacements . concat ( b . replacements ) ;
a . text += b . text ;
return a ;
}
/ * *
* Combine all Rich Text values into one . This is similar to
* ` String.prototype.concat ` .
*
2020-10-13 15:10:30 +02:00
* @ param { ... RichTextValue } values Objects to combine .
2019-03-21 13:48:00 +01:00
*
2020-10-13 15:10:30 +02:00
* @ return { RichTextValue } A new value combining all given records .
2019-03-21 13:48:00 +01:00
* /
2023-06-27 16:24:19 +02:00
function concat ( ... values ) {
2019-03-21 13:48:00 +01:00
return normaliseFormats ( values . reduce ( mergePair , create ( ) ) ) ;
}
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/get-active-formats.js
2023-06-27 16:24:19 +02:00
/** @typedef {import('./types').RichTextValue} RichTextValue */
2020-10-13 15:10:30 +02:00
2023-06-27 16:24:19 +02:00
/** @typedef {import('./types').RichTextFormatList} RichTextFormatList */
/ * *
* Internal dependencies
* /
2020-10-13 15:10:30 +02:00
2019-03-07 10:09:59 +01:00
/ * *
* Gets the all format objects at the start of the selection .
*
2020-10-13 15:10:30 +02:00
* @ param { RichTextValue } value Value to inspect .
* @ param { Array } EMPTY _ACTIVE _FORMATS Array to return if there are no
* active formats .
2019-03-07 10:09:59 +01:00
*
2020-10-13 15:10:30 +02:00
* @ return { RichTextFormatList } Active format objects .
2019-03-07 10:09:59 +01:00
* /
2023-06-27 16:24:19 +02:00
function getActiveFormats ( value , EMPTY _ACTIVE _FORMATS = [ ] ) {
const {
2021-11-15 13:50:17 +01:00
formats ,
start ,
end ,
activeFormats
2023-06-27 16:24:19 +02:00
} = value ;
2021-11-15 13:50:17 +01:00
2019-03-07 10:09:59 +01:00
if ( start === undefined ) {
2020-01-22 23:06:21 +01:00
return EMPTY _ACTIVE _FORMATS ;
2019-03-07 10:09:59 +01:00
}
Block Editor: Update packages to bring a selection of bugfixes in.
Props iseulde, kjellr, aduth, 0mirka00, mcsf, nosolosw, gziolo, jasmussen, talldanwp, notnownikki, swissspidy, jorgefilipecosta, noisysocks.
See https://github.com/WordPress/gutenberg/pull/14796.
Fixes #46801.
Built from https://develop.svn.wordpress.org/trunk@45138
git-svn-id: http://core.svn.wordpress.org/trunk@44947 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2019-04-08 08:37:57 +02:00
if ( start === end ) {
// For a collapsed caret, it is possible to override the active formats.
if ( activeFormats ) {
return activeFormats ;
}
2021-05-19 17:09:27 +02:00
const formatsBefore = formats [ start - 1 ] || EMPTY _ACTIVE _FORMATS ;
const formatsAfter = formats [ start ] || EMPTY _ACTIVE _FORMATS ; // By default, select the lowest amount of formats possible (which means
Block Editor: Update packages to bring a selection of bugfixes in.
Props iseulde, kjellr, aduth, 0mirka00, mcsf, nosolosw, gziolo, jasmussen, talldanwp, notnownikki, swissspidy, jorgefilipecosta, noisysocks.
See https://github.com/WordPress/gutenberg/pull/14796.
Fixes #46801.
Built from https://develop.svn.wordpress.org/trunk@45138
git-svn-id: http://core.svn.wordpress.org/trunk@44947 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2019-04-08 08:37:57 +02:00
// the caret is positioned outside the format boundary). The user can
// then use arrow keys to define `activeFormats`.
if ( formatsBefore . length < formatsAfter . length ) {
return formatsBefore ;
}
2019-03-07 10:09:59 +01:00
Block Editor: Update packages to bring a selection of bugfixes in.
Props iseulde, kjellr, aduth, 0mirka00, mcsf, nosolosw, gziolo, jasmussen, talldanwp, notnownikki, swissspidy, jorgefilipecosta, noisysocks.
See https://github.com/WordPress/gutenberg/pull/14796.
Fixes #46801.
Built from https://develop.svn.wordpress.org/trunk@45138
git-svn-id: http://core.svn.wordpress.org/trunk@44947 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2019-04-08 08:37:57 +02:00
return formatsAfter ;
2023-06-27 16:24:19 +02:00
} // If there's no formats at the start index, there are not active formats.
if ( ! formats [ start ] ) {
return EMPTY _ACTIVE _FORMATS ;
2019-03-07 10:09:59 +01:00
}
2023-06-27 16:24:19 +02:00
const selectedFormats = formats . slice ( start , end ) ; // Clone the formats so we're not mutating the live value.
const _activeFormats = [ ... selectedFormats [ 0 ] ] ;
let i = selectedFormats . length ; // For performance reasons, start from the end where it's much quicker to
// realise that there are no active formats.
while ( i -- ) {
const formatsAtIndex = selectedFormats [ i ] ; // If we run into any index without formats, we're sure that there's no
// active formats.
if ( ! formatsAtIndex ) {
return EMPTY _ACTIVE _FORMATS ;
}
let ii = _activeFormats . length ; // Loop over the active formats and remove any that are not present at
// the current index.
while ( ii -- ) {
const format = _activeFormats [ ii ] ;
if ( ! formatsAtIndex . find ( _format => isFormatEqual ( format , _format ) ) ) {
_activeFormats . splice ( ii , 1 ) ;
}
} // If there are no active formats, we can stop.
if ( _activeFormats . length === 0 ) {
return EMPTY _ACTIVE _FORMATS ;
}
}
return _activeFormats || EMPTY _ACTIVE _FORMATS ;
2018-12-18 04:14:52 +01:00
}
2018-12-15 12:00:40 +01:00
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/get-active-format.js
2019-03-07 10:09:59 +01:00
/ * *
* Internal dependencies
* /
2023-06-27 16:24:19 +02:00
/** @typedef {import('./types').RichTextValue} RichTextValue */
2020-10-13 15:10:30 +02:00
2023-06-27 16:24:19 +02:00
/** @typedef {import('./types').RichTextFormat} RichTextFormat */
2020-10-13 15:10:30 +02:00
2018-12-14 05:41:57 +01:00
/ * *
2018-12-18 04:14:52 +01:00
* Gets the format object by type at the start of the selection . This can be
* used to get e . g . the URL of a link format at the current selection , but also
* to check if a format is active at the selection . Returns undefined if there
* is no format at the selection .
2018-12-14 05:41:57 +01:00
*
2020-10-13 15:10:30 +02:00
* @ param { RichTextValue } value Value to inspect .
* @ param { string } formatType Format type to look for .
2018-12-14 05:41:57 +01:00
*
2020-10-13 15:10:30 +02:00
* @ return { RichTextFormat | undefined } Active format object of the specified
* type , or undefined .
2018-12-14 05:41:57 +01:00
* /
2019-03-07 10:09:59 +01:00
function getActiveFormat ( value , formatType ) {
2023-06-27 16:24:19 +02:00
return getActiveFormats ( value ) . find ( ( {
type
} ) => type === formatType ) ;
2018-12-14 05:41:57 +01:00
}
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/get-active-object.js
2019-03-21 13:48:00 +01:00
/ * *
* Internal dependencies
* /
2023-06-27 16:24:19 +02:00
/** @typedef {import('./types').RichTextValue} RichTextValue */
2020-10-13 15:10:30 +02:00
2023-06-27 16:24:19 +02:00
/** @typedef {import('./types').RichTextFormat} RichTextFormat */
2020-10-13 15:10:30 +02:00
2019-03-21 13:48:00 +01:00
/ * *
* Gets the active object , if there is any .
*
2020-10-13 15:10:30 +02:00
* @ param { RichTextValue } value Value to inspect .
2019-03-21 13:48:00 +01:00
*
2020-10-13 15:10:30 +02:00
* @ return { RichTextFormat | void } Active object , or undefined .
2019-03-21 13:48:00 +01:00
* /
2023-06-27 16:24:19 +02:00
function getActiveObject ( {
start ,
end ,
replacements ,
text
} ) {
2019-03-21 13:48:00 +01:00
if ( start + 1 !== end || text [ start ] !== OBJECT _REPLACEMENT _CHARACTER ) {
return ;
}
return replacements [ start ] ;
}
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/get-text-content.js
2021-04-15 17:19:43 +02:00
/ * *
* Internal dependencies
* /
2023-06-27 16:24:19 +02:00
/** @typedef {import('./types').RichTextValue} RichTextValue */
2020-10-13 15:10:30 +02:00
2022-09-20 17:43:29 +02:00
const pattern = new RegExp ( ` [ ${ OBJECT _REPLACEMENT _CHARACTER } ${ LINE _SEPARATOR } ] ` , 'g' ) ;
2019-09-19 17:19:18 +02:00
/ * *
* Get the textual content of a Rich Text value . This is similar to
* ` Element.textContent ` .
*
2020-10-13 15:10:30 +02:00
* @ param { RichTextValue } value Value to use .
2019-09-19 17:19:18 +02:00
*
* @ return { string } The text content .
* /
2021-04-15 17:19:43 +02:00
2023-06-27 16:24:19 +02:00
function getTextContent ( {
text
} ) {
2022-09-20 17:43:29 +02:00
return text . replace ( pattern , c => c === OBJECT _REPLACEMENT _CHARACTER ? '' : '\n' ) ;
2018-12-18 04:14:52 +01:00
}
2018-12-14 05:41:57 +01:00
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/is-collapsed.js
2023-06-27 16:24:19 +02:00
/ * *
* Internal dependencies
* /
2020-10-13 15:10:30 +02:00
2018-12-18 04:14:52 +01:00
/ * *
* Check if the selection of a Rich Text value is collapsed or not . Collapsed
* means that no characters are selected , but there is a caret present . If there
* is no selection , ` undefined ` will be returned . This is similar to
* ` window.getSelection().isCollapsed() ` .
*
2023-06-27 16:24:19 +02:00
* @ param props The rich text value to check .
* @ param props . start
* @ param props . end
* @ return True if the selection is collapsed , false if not , undefined if there is no selection .
* /
function isCollapsed ( {
start ,
end
} ) {
2018-12-18 04:14:52 +01:00
if ( start === undefined || end === undefined ) {
return ;
2018-12-14 05:41:57 +01:00
}
2018-12-18 04:14:52 +01:00
return start === end ;
2018-12-14 05:41:57 +01:00
}
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/is-empty.js
2019-03-21 13:48:00 +01:00
/ * *
* Internal dependencies
* /
2023-06-27 16:24:19 +02:00
/** @typedef {import('./types').RichTextValue} RichTextValue */
2020-10-13 15:10:30 +02:00
2019-03-21 13:48:00 +01:00
/ * *
* Check if a Rich Text value is Empty , meaning it contains no text or any
* objects ( such as images ) .
*
2020-10-13 15:10:30 +02:00
* @ param { RichTextValue } value Value to use .
2019-03-21 13:48:00 +01:00
*
* @ return { boolean } True if the value is empty , false if not .
* /
2023-06-27 16:24:19 +02:00
function isEmpty ( {
text
} ) {
2019-03-21 13:48:00 +01:00
return text . length === 0 ;
}
/ * *
* Check if the current collapsed selection is on an empty line in case of a
* multiline value .
*
2021-11-08 15:29:21 +01:00
* @ param { RichTextValue } value Value te check .
2019-03-21 13:48:00 +01:00
*
* @ return { boolean } True if the line is empty , false if not .
* /
2023-06-27 16:24:19 +02:00
function isEmptyLine ( {
text ,
start ,
end
} ) {
2019-03-21 13:48:00 +01:00
if ( start !== end ) {
return false ;
}
if ( text . length === 0 ) {
return true ;
}
if ( start === 0 && text . slice ( 0 , 1 ) === LINE _SEPARATOR ) {
return true ;
}
if ( start === text . length && text . slice ( - 1 ) === LINE _SEPARATOR ) {
return true ;
}
2021-05-19 17:09:27 +02:00
return text . slice ( start - 1 , end + 1 ) === ` ${ LINE _SEPARATOR } ${ LINE _SEPARATOR } ` ;
2019-03-21 13:48:00 +01:00
}
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/join.js
2018-12-14 05:41:57 +01:00
/ * *
* Internal dependencies
* /
2023-06-27 16:24:19 +02:00
/** @typedef {import('./types').RichTextValue} RichTextValue */
2020-10-13 15:10:30 +02:00
2018-12-14 05:41:57 +01:00
/ * *
* Combine an array of Rich Text values into one , optionally separated by
* ` separator ` , which can be a Rich Text value , HTML string , or plain text
* string . This is similar to ` Array.prototype.join ` .
*
2020-10-13 15:10:30 +02:00
* @ param { Array < RichTextValue > } values An array of values to join .
* @ param { string | RichTextValue } [ separator ] Separator string or value .
2018-12-14 05:41:57 +01:00
*
2020-10-13 15:10:30 +02:00
* @ return { RichTextValue } A new combined value .
2018-12-14 05:41:57 +01:00
* /
2023-06-27 16:24:19 +02:00
function join ( values , separator = '' ) {
2018-12-14 05:41:57 +01:00
if ( typeof separator === 'string' ) {
2018-12-18 04:14:52 +01:00
separator = create ( {
2018-12-14 05:41:57 +01:00
text : separator
} ) ;
}
2023-06-27 16:24:19 +02:00
return normaliseFormats ( values . reduce ( ( accumlator , {
formats ,
replacements ,
text
} ) => ( {
formats : accumlator . formats . concat ( separator . formats , formats ) ,
replacements : accumlator . replacements . concat ( separator . replacements , replacements ) ,
text : accumlator . text + separator . text + text
} ) ) ) ;
2018-12-14 05:41:57 +01:00
}
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/register-format-type.js
2018-12-14 12:02:53 +01:00
/ * *
* WordPress dependencies
* /
2021-01-28 03:04:13 +01:00
/ * *
* Internal dependencies
* /
2020-01-08 12:57:23 +01:00
/ * *
* @ typedef { Object } WPFormat
*
* @ property { string } name A string identifying the format . Must be
* unique across all registered formats .
* @ property { string } tagName The HTML tag this format will wrap the
* selection with .
* @ property { string } [ className ] A class to match the format .
* @ property { string } title Name of the format .
* @ property { Function } edit Should return a component for the user to
* interact with the new registered format .
* /
2018-12-14 12:02:53 +01:00
/ * *
* Registers a new format provided a unique name and an object defining its
* behavior .
*
2021-11-08 15:29:21 +01:00
* @ param { string } name Format name .
* @ param { WPFormat } settings Format settings .
2018-12-14 12:02:53 +01:00
*
2020-10-13 15:10:30 +02:00
* @ return { WPFormat | undefined } The format , if it has been successfully
* registered ; otherwise ` undefined ` .
2018-12-14 12:02:53 +01:00
* /
function registerFormatType ( name , settings ) {
2021-05-19 17:09:27 +02:00
settings = {
name ,
... settings
} ;
2018-12-14 12:02:53 +01:00
if ( typeof settings . name !== 'string' ) {
window . console . error ( 'Format names must be strings.' ) ;
return ;
}
if ( ! /^[a-z][a-z0-9-]*\/[a-z][a-z0-9-]*$/ . test ( settings . name ) ) {
window . console . error ( 'Format names must contain a namespace prefix, include only lowercase alphanumeric characters or dashes, and start with a letter. Example: my-plugin/my-custom-format' ) ;
return ;
}
2022-04-11 14:04:30 +02:00
if ( ( 0 , external _wp _data _namespaceObject . select ) ( store ) . getFormatType ( settings . name ) ) {
2018-12-14 12:02:53 +01:00
window . console . error ( 'Format "' + settings . name + '" is already registered.' ) ;
return ;
}
2018-12-17 05:52:00 +01:00
if ( typeof settings . tagName !== 'string' || settings . tagName === '' ) {
window . console . error ( 'Format tag names must be a string.' ) ;
return ;
}
if ( ( typeof settings . className !== 'string' || settings . className === '' ) && settings . className !== null ) {
window . console . error ( 'Format class names must be a string, or null to handle bare elements.' ) ;
return ;
}
if ( ! /^[_a-zA-Z]+[a-zA-Z0-9-]*$/ . test ( settings . className ) ) {
window . console . error ( 'A class name must begin with a letter, followed by any number of hyphens, letters, or numbers.' ) ;
2018-12-14 12:02:53 +01:00
return ;
}
2018-12-17 05:52:00 +01:00
if ( settings . className === null ) {
2022-04-11 14:04:30 +02:00
const formatTypeForBareElement = ( 0 , external _wp _data _namespaceObject . select ) ( store ) . getFormatTypeForBareElement ( settings . tagName ) ;
2018-12-17 05:52:00 +01:00
2023-02-07 08:04:52 +01:00
if ( formatTypeForBareElement && formatTypeForBareElement . name !== 'core/unknown' ) {
2021-05-19 17:09:27 +02:00
window . console . error ( ` Format " ${ formatTypeForBareElement . name } " is already registered to handle bare tag name " ${ settings . tagName } ". ` ) ;
2018-12-17 05:52:00 +01:00
return ;
}
} else {
2022-04-11 14:04:30 +02:00
const formatTypeForClassName = ( 0 , external _wp _data _namespaceObject . select ) ( store ) . getFormatTypeForClassName ( settings . className ) ;
2018-12-17 05:52:00 +01:00
if ( formatTypeForClassName ) {
2021-05-19 17:09:27 +02:00
window . console . error ( ` Format " ${ formatTypeForClassName . name } " is already registered to handle class name " ${ settings . className } ". ` ) ;
2018-12-17 05:52:00 +01:00
return ;
}
}
2018-12-14 12:02:53 +01:00
if ( ! ( 'title' in settings ) || settings . title === '' ) {
window . console . error ( 'The format "' + settings . name + '" must have a title.' ) ;
return ;
}
if ( 'keywords' in settings && settings . keywords . length > 3 ) {
window . console . error ( 'The format "' + settings . name + '" can have a maximum of 3 keywords.' ) ;
2020-01-22 23:06:21 +01:00
return ;
}
Block Editor: Update `@wordpress` dependencies to match Gutenberg 4.5.1.
- Update the annotations, api-fetch, block-library, blocks, components, compose, core-data, data, date, dom, edit-post, editor, element, format-library, html-entities, i18n, jest-console, jest-preset-default, keycodes, list-reusable-blocks, notices, nux, plugins, rich-text, scripts, token-lists, url, viewport packages.
- Upgrades React from 16.5.2 to 16.6.3.
- Adds a missing `wp-date` dependency to the editor script.
- Updates changed dependencies in `script-loader.php`.
- Fixes undefined notices in some blocks.
- Removes incorrect `gutenberg` textdomain.
Merges [43891], [43903], and [43919] to trunk.
Props atimmer, aduth, youknowriad, danielbachhuber.
See #45145.
Built from https://develop.svn.wordpress.org/trunk@44262
git-svn-id: http://core.svn.wordpress.org/trunk@44092 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2018-12-17 16:37:00 +01:00
2020-01-22 23:06:21 +01:00
if ( typeof settings . title !== 'string' ) {
window . console . error ( 'Format titles must be strings.' ) ;
return ;
2018-12-17 05:52:00 +01:00
}
2022-04-11 14:04:30 +02:00
( 0 , external _wp _data _namespaceObject . dispatch ) ( store ) . addFormatTypes ( settings ) ;
2018-12-14 12:02:53 +01:00
return settings ;
}
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/remove-format.js
2018-12-14 05:41:57 +01:00
/ * *
* Internal dependencies
* /
2023-06-27 16:24:19 +02:00
/** @typedef {import('./types').RichTextValue} RichTextValue */
2020-10-13 15:10:30 +02:00
2018-12-14 05:41:57 +01:00
/ * *
* Remove any format object from a Rich Text value by type from the given
* ` startIndex ` to the given ` endIndex ` . Indices are retrieved from the
* selection if none are provided .
*
2020-10-13 15:10:30 +02:00
* @ param { RichTextValue } value Value to modify .
* @ param { string } formatType Format type to remove .
* @ param { number } [ startIndex ] Start index .
* @ param { number } [ endIndex ] End index .
2018-12-14 05:41:57 +01:00
*
2020-10-13 15:10:30 +02:00
* @ return { RichTextValue } A new value with the format applied .
2018-12-14 05:41:57 +01:00
* /
2023-06-27 16:24:19 +02:00
function removeFormat ( value , formatType , startIndex = value . start , endIndex = value . end ) {
2021-05-19 17:09:27 +02:00
const {
formats ,
activeFormats
} = value ;
const newFormats = formats . slice ( ) ; // If the selection is collapsed, expand start and end to the edges of the
2018-12-14 05:41:57 +01:00
// format.
if ( startIndex === endIndex ) {
2023-06-27 16:24:19 +02:00
const format = newFormats [ startIndex ] ? . find ( ( {
type
} ) => type === formatType ) ;
2018-12-14 05:41:57 +01:00
2019-03-21 13:48:00 +01:00
if ( format ) {
2023-06-27 16:24:19 +02:00
while ( newFormats [ startIndex ] ? . find ( newFormat => newFormat === format ) ) {
2019-03-21 13:48:00 +01:00
filterFormats ( newFormats , startIndex , formatType ) ;
startIndex -- ;
}
2018-12-14 05:41:57 +01:00
endIndex ++ ;
2019-03-21 13:48:00 +01:00
2023-06-27 16:24:19 +02:00
while ( newFormats [ endIndex ] ? . find ( newFormat => newFormat === format ) ) {
2019-03-21 13:48:00 +01:00
filterFormats ( newFormats , endIndex , formatType ) ;
endIndex ++ ;
}
2018-12-14 05:41:57 +01:00
}
} else {
2021-05-19 17:09:27 +02:00
for ( let i = startIndex ; i < endIndex ; i ++ ) {
2018-12-14 05:41:57 +01:00
if ( newFormats [ i ] ) {
filterFormats ( newFormats , i , formatType ) ;
}
}
}
2021-05-19 17:09:27 +02:00
return normaliseFormats ( { ... value ,
2019-05-16 20:08:00 +02:00
formats : newFormats ,
2023-06-27 16:24:19 +02:00
activeFormats : activeFormats ? . filter ( ( {
type
} ) => type !== formatType ) || [ ]
2021-05-19 17:09:27 +02:00
} ) ;
2018-12-14 05:41:57 +01:00
}
function filterFormats ( formats , index , formatType ) {
2023-06-27 16:24:19 +02:00
const newFormats = formats [ index ] . filter ( ( {
type
} ) => type !== formatType ) ;
2018-12-14 05:41:57 +01:00
if ( newFormats . length ) {
formats [ index ] = newFormats ;
} else {
delete formats [ index ] ;
}
}
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/insert.js
2018-12-18 04:14:52 +01:00
/ * *
* Internal dependencies
* /
2018-12-14 05:41:57 +01:00
2023-06-27 16:24:19 +02:00
/** @typedef {import('./types').RichTextValue} RichTextValue */
2020-10-13 15:10:30 +02:00
2018-12-18 04:14:52 +01:00
/ * *
* Insert a Rich Text value , an HTML string , or a plain text string , into a
* Rich Text value at the given ` startIndex ` . Any content between ` startIndex `
* and ` endIndex ` will be removed . Indices are retrieved from the selection if
* none are provided .
*
2020-10-13 15:10:30 +02:00
* @ param { RichTextValue } value Value to modify .
* @ param { RichTextValue | string } valueToInsert Value to insert .
* @ param { number } [ startIndex ] Start index .
* @ param { number } [ endIndex ] End index .
2018-12-18 04:14:52 +01:00
*
2020-10-13 15:10:30 +02:00
* @ return { RichTextValue } A new value with the value inserted .
2018-12-18 04:14:52 +01:00
* /
2018-12-14 05:41:57 +01:00
2023-06-27 16:24:19 +02:00
function insert ( value , valueToInsert , startIndex = value . start , endIndex = value . end ) {
2021-05-19 17:09:27 +02:00
const {
formats ,
replacements ,
text
} = value ;
2018-12-18 04:14:52 +01:00
if ( typeof valueToInsert === 'string' ) {
valueToInsert = create ( {
text : valueToInsert
} ) ;
}
2021-05-19 17:09:27 +02:00
const index = startIndex + valueToInsert . text . length ;
2018-12-18 04:14:52 +01:00
return normaliseFormats ( {
formats : formats . slice ( 0 , startIndex ) . concat ( valueToInsert . formats , formats . slice ( endIndex ) ) ,
2019-03-21 13:48:00 +01:00
replacements : replacements . slice ( 0 , startIndex ) . concat ( valueToInsert . replacements , replacements . slice ( endIndex ) ) ,
2018-12-18 04:14:52 +01:00
text : text . slice ( 0 , startIndex ) + valueToInsert . text + text . slice ( endIndex ) ,
start : index ,
end : index
} ) ;
}
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/remove.js
2018-12-14 05:41:57 +01:00
/ * *
* Internal dependencies
* /
2023-06-27 16:24:19 +02:00
/** @typedef {import('./types').RichTextValue} RichTextValue */
2020-10-13 15:10:30 +02:00
2018-12-14 05:41:57 +01:00
/ * *
* Remove content from a Rich Text value between the given ` startIndex ` and
* ` endIndex ` . Indices are retrieved from the selection if none are provided .
*
2020-10-13 15:10:30 +02:00
* @ param { RichTextValue } value Value to modify .
* @ param { number } [ startIndex ] Start index .
* @ param { number } [ endIndex ] End index .
2018-12-14 05:41:57 +01:00
*
2020-10-13 15:10:30 +02:00
* @ return { RichTextValue } A new value with the content removed .
2018-12-14 05:41:57 +01:00
* /
2022-04-11 14:04:30 +02:00
function remove ( value , startIndex , endIndex ) {
2018-12-18 04:14:52 +01:00
return insert ( value , create ( ) , startIndex , endIndex ) ;
2018-12-14 05:41:57 +01:00
}
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/replace.js
2018-12-14 05:41:57 +01:00
/ * *
* Internal dependencies
* /
2023-06-27 16:24:19 +02:00
/** @typedef {import('./types').RichTextValue} RichTextValue */
2020-10-13 15:10:30 +02:00
2018-12-14 05:41:57 +01:00
/ * *
* Search a Rich Text value and replace the match ( es ) with ` replacement ` . This
* is similar to ` String.prototype.replace ` .
*
2021-11-08 15:29:21 +01:00
* @ param { RichTextValue } value The value to modify .
* @ param { RegExp | string } pattern A RegExp object or literal . Can also be
2018-12-14 05:41:57 +01:00
* a string . It is treated as a verbatim
* string and is not interpreted as a
* regular expression . Only the first
* occurrence will be replaced .
* @ param { Function | string } replacement The match or matches are replaced with
* the specified or the value returned by
* the specified function .
*
2020-10-13 15:10:30 +02:00
* @ return { RichTextValue } A new value with replacements applied .
2018-12-14 05:41:57 +01:00
* /
2023-06-27 16:24:19 +02:00
function replace _replace ( {
formats ,
replacements ,
text ,
start ,
end
} , pattern , replacement ) {
text = text . replace ( pattern , ( match , ... rest ) => {
2021-05-19 17:09:27 +02:00
const offset = rest [ rest . length - 2 ] ;
let newText = replacement ;
let newFormats ;
let newReplacements ;
2018-12-14 05:41:57 +01:00
if ( typeof newText === 'function' ) {
2021-05-19 17:09:27 +02:00
newText = replacement ( match , ... rest ) ;
2018-12-14 05:41:57 +01:00
}
2021-05-19 17:09:27 +02:00
if ( typeof newText === 'object' ) {
2018-12-14 05:41:57 +01:00
newFormats = newText . formats ;
2019-03-21 13:48:00 +01:00
newReplacements = newText . replacements ;
2018-12-14 05:41:57 +01:00
newText = newText . text ;
} else {
newFormats = Array ( newText . length ) ;
2019-03-21 13:48:00 +01:00
newReplacements = Array ( newText . length ) ;
2018-12-14 05:41:57 +01:00
if ( formats [ offset ] ) {
newFormats = newFormats . fill ( formats [ offset ] ) ;
}
}
formats = formats . slice ( 0 , offset ) . concat ( newFormats , formats . slice ( offset + match . length ) ) ;
2019-03-21 13:48:00 +01:00
replacements = replacements . slice ( 0 , offset ) . concat ( newReplacements , replacements . slice ( offset + match . length ) ) ;
2018-12-14 05:41:57 +01:00
if ( start ) {
start = end = offset + newText . length ;
}
return newText ;
} ) ;
2018-12-18 04:14:52 +01:00
return normaliseFormats ( {
2021-05-19 17:09:27 +02:00
formats ,
replacements ,
text ,
start ,
end
2018-12-14 05:41:57 +01:00
} ) ;
}
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/insert-line-separator.js
2018-12-18 04:14:52 +01:00
/ * *
* Internal dependencies
* /
2018-12-14 05:41:57 +01:00
2023-06-27 16:24:19 +02:00
/** @typedef {import('./types').RichTextValue} RichTextValue */
2020-10-13 15:10:30 +02:00
2018-12-18 04:14:52 +01:00
/ * *
* Insert a line break character into a Rich Text value at the given
* ` startIndex ` . Any content between ` startIndex ` and ` endIndex ` will be
* removed . Indices are retrieved from the selection if none are provided .
*
2020-10-13 15:10:30 +02:00
* @ param { RichTextValue } value Value to modify .
* @ param { number } [ startIndex ] Start index .
* @ param { number } [ endIndex ] End index .
2018-12-18 04:14:52 +01:00
*
2020-10-13 15:10:30 +02:00
* @ return { RichTextValue } A new value with the value inserted .
2018-12-18 04:14:52 +01:00
* /
2023-06-27 16:24:19 +02:00
function insertLineSeparator ( value , startIndex = value . start , endIndex = value . end ) {
2021-05-19 17:09:27 +02:00
const beforeText = value . text . slice ( 0 , startIndex ) ;
const previousLineSeparatorIndex = beforeText . lastIndexOf ( LINE _SEPARATOR ) ;
const previousLineSeparatorFormats = value . replacements [ previousLineSeparatorIndex ] ;
let replacements = [ , ] ;
2018-12-18 04:14:52 +01:00
if ( previousLineSeparatorFormats ) {
2019-03-21 13:48:00 +01:00
replacements = [ previousLineSeparatorFormats ] ;
2018-12-18 04:14:52 +01:00
}
2021-05-19 17:09:27 +02:00
const valueToInsert = {
2019-03-21 13:48:00 +01:00
formats : [ , ] ,
2021-05-19 17:09:27 +02:00
replacements ,
2018-12-18 04:14:52 +01:00
text : LINE _SEPARATOR
} ;
return insert ( value , valueToInsert , startIndex , endIndex ) ;
}
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/insert-object.js
2018-12-18 04:14:52 +01:00
/ * *
* Internal dependencies
* /
2020-10-13 15:10:30 +02:00
2023-06-27 16:24:19 +02:00
/** @typedef {import('./types').RichTextValue} RichTextValue */
2020-10-13 15:10:30 +02:00
2023-06-27 16:24:19 +02:00
/** @typedef {import('./types').RichTextFormat} RichTextFormat */
2020-10-13 15:10:30 +02:00
2018-12-18 04:14:52 +01:00
/ * *
* Insert a format as an object into a Rich Text value at the given
* ` startIndex ` . Any content between ` startIndex ` and ` endIndex ` will be
* removed . Indices are retrieved from the selection if none are provided .
*
2020-10-13 15:10:30 +02:00
* @ param { RichTextValue } value Value to modify .
* @ param { RichTextFormat } formatToInsert Format to insert as object .
* @ param { number } [ startIndex ] Start index .
* @ param { number } [ endIndex ] End index .
2018-12-18 04:14:52 +01:00
*
2020-10-13 15:10:30 +02:00
* @ return { RichTextValue } A new value with the object inserted .
2018-12-18 04:14:52 +01:00
* /
function insertObject ( value , formatToInsert , startIndex , endIndex ) {
2021-05-19 17:09:27 +02:00
const valueToInsert = {
2019-03-21 13:48:00 +01:00
formats : [ , ] ,
replacements : [ formatToInsert ] ,
2020-10-13 15:10:30 +02:00
text : OBJECT _REPLACEMENT _CHARACTER
2018-12-18 04:14:52 +01:00
} ;
return insert ( value , valueToInsert , startIndex , endIndex ) ;
}
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/slice.js
2023-06-27 16:24:19 +02:00
/** @typedef {import('./types').RichTextValue} RichTextValue */
2020-10-13 15:10:30 +02:00
2018-12-14 05:41:57 +01:00
/ * *
* Slice a Rich Text value from ` startIndex ` to ` endIndex ` . Indices are
* retrieved from the selection if none are provided . This is similar to
* ` String.prototype.slice ` .
*
2020-10-13 15:10:30 +02:00
* @ param { RichTextValue } value Value to modify .
* @ param { number } [ startIndex ] Start index .
* @ param { number } [ endIndex ] End index .
2018-12-14 05:41:57 +01:00
*
2020-10-13 15:10:30 +02:00
* @ return { RichTextValue } A new extracted value .
2018-12-14 05:41:57 +01:00
* /
2023-06-27 16:24:19 +02:00
function slice ( value , startIndex = value . start , endIndex = value . end ) {
2021-05-19 17:09:27 +02:00
const {
formats ,
replacements ,
text
} = value ;
2018-12-14 05:41:57 +01:00
if ( startIndex === undefined || endIndex === undefined ) {
2021-05-19 17:09:27 +02:00
return { ... value
} ;
2018-12-14 05:41:57 +01:00
}
return {
formats : formats . slice ( startIndex , endIndex ) ,
2019-03-21 13:48:00 +01:00
replacements : replacements . slice ( startIndex , endIndex ) ,
2018-12-14 05:41:57 +01:00
text : text . slice ( startIndex , endIndex )
} ;
}
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/split.js
2018-12-14 05:41:57 +01:00
/ * *
* Internal dependencies
* /
2023-06-27 16:24:19 +02:00
/** @typedef {import('./types').RichTextValue} RichTextValue */
2020-10-13 15:10:30 +02:00
2018-12-14 05:41:57 +01:00
/ * *
* Split a Rich Text value in two at the given ` startIndex ` and ` endIndex ` , or
* split at the given separator . This is similar to ` String.prototype.split ` .
* Indices are retrieved from the selection if none are provided .
*
2020-10-13 15:10:30 +02:00
* @ param { RichTextValue } value
2019-03-21 13:48:00 +01:00
* @ param { number | string } [ string ] Start index , or string at which to split .
2018-12-14 05:41:57 +01:00
*
2021-05-21 12:14:23 +02:00
* @ return { Array < RichTextValue > | undefined } An array of new values .
2018-12-14 05:41:57 +01:00
* /
2023-06-27 16:24:19 +02:00
function split ( {
formats ,
replacements ,
text ,
start ,
end
} , string ) {
2018-12-14 05:41:57 +01:00
if ( typeof string !== 'string' ) {
2021-05-19 17:09:27 +02:00
return splitAtSelection ( ... arguments ) ;
2018-12-14 05:41:57 +01:00
}
2021-05-19 17:09:27 +02:00
let nextStart = 0 ;
return text . split ( string ) . map ( substring => {
const startIndex = nextStart ;
const value = {
2018-12-14 05:41:57 +01:00
formats : formats . slice ( startIndex , startIndex + substring . length ) ,
2019-03-21 13:48:00 +01:00
replacements : replacements . slice ( startIndex , startIndex + substring . length ) ,
2018-12-14 05:41:57 +01:00
text : substring
} ;
nextStart += string . length + substring . length ;
if ( start !== undefined && end !== undefined ) {
if ( start >= startIndex && start < nextStart ) {
value . start = start - startIndex ;
} else if ( start < startIndex && end > startIndex ) {
value . start = 0 ;
}
if ( end >= startIndex && end < nextStart ) {
value . end = end - startIndex ;
} else if ( start < nextStart && end > nextStart ) {
value . end = substring . length ;
}
}
return value ;
} ) ;
}
2023-06-27 16:24:19 +02:00
function splitAtSelection ( {
formats ,
replacements ,
text ,
start ,
end
} , startIndex = start , endIndex = end ) {
2021-05-21 12:14:23 +02:00
if ( start === undefined || end === undefined ) {
return ;
}
2021-05-19 17:09:27 +02:00
const before = {
2018-12-14 05:41:57 +01:00
formats : formats . slice ( 0 , startIndex ) ,
2019-03-21 13:48:00 +01:00
replacements : replacements . slice ( 0 , startIndex ) ,
2018-12-14 05:41:57 +01:00
text : text . slice ( 0 , startIndex )
} ;
2021-05-19 17:09:27 +02:00
const after = {
2018-12-14 05:41:57 +01:00
formats : formats . slice ( endIndex ) ,
2019-03-21 13:48:00 +01:00
replacements : replacements . slice ( endIndex ) ,
2018-12-14 05:41:57 +01:00
text : text . slice ( endIndex ) ,
start : 0 ,
end : 0
} ;
return [ // Ensure newlines are trimmed.
2019-09-19 17:19:18 +02:00
replace _replace ( before , /\u2028+$/ , '' ) , replace _replace ( after , /^\u2028+/ , '' ) ] ;
2018-12-14 05:41:57 +01:00
}
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/get-format-type.js
2018-12-14 12:02:53 +01:00
/ * *
2018-12-18 04:14:52 +01:00
* WordPress dependencies
2018-12-14 12:02:53 +01:00
* /
2021-01-28 03:04:13 +01:00
/ * *
* Internal dependencies
* /
2020-10-13 15:10:30 +02:00
/** @typedef {import('./register-format-type').RichTextFormatType} RichTextFormatType */
2018-12-14 12:02:53 +01:00
/ * *
2018-12-18 04:14:52 +01:00
* Returns a registered format type .
2018-12-14 12:02:53 +01:00
*
2018-12-18 04:14:52 +01:00
* @ param { string } name Format name .
2018-12-14 12:02:53 +01:00
*
2020-10-13 15:10:30 +02:00
* @ return { RichTextFormatType | undefined } Format type .
2018-12-14 12:02:53 +01:00
* /
2018-12-18 04:14:52 +01:00
function get _format _type _getFormatType ( name ) {
2022-04-11 14:04:30 +02:00
return ( 0 , external _wp _data _namespaceObject . select ) ( store ) . getFormatType ( name ) ;
2018-12-14 12:02:53 +01:00
}
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/to-tree.js
2018-12-14 12:02:53 +01:00
/ * *
* Internal dependencies
* /
2021-07-14 01:58:30 +02:00
function restoreOnAttributes ( attributes , isEditableTree ) {
if ( isEditableTree ) {
return attributes ;
}
const newAttributes = { } ;
for ( const key in attributes ) {
let newKey = key ;
if ( key . startsWith ( 'data-disable-rich-text-' ) ) {
newKey = key . slice ( 'data-disable-rich-text-' . length ) ;
}
newAttributes [ newKey ] = attributes [ key ] ;
}
return newAttributes ;
}
2019-03-07 10:09:59 +01:00
/ * *
* Converts a format object to information that can be used to create an element
* from ( type , attributes and object ) .
*
2021-11-08 15:29:21 +01:00
* @ param { Object } $1 Named parameters .
* @ param { string } $1 . type The format type .
2023-02-07 08:04:52 +01:00
* @ param { string } $1 . tagName The tag name .
2021-11-08 15:29:21 +01:00
* @ param { Object } $1 . attributes The format attributes .
* @ param { Object } $1 . unregisteredAttributes The unregistered format
* attributes .
* @ param { boolean } $1 . object Whether or not it is an object
* format .
* @ param { boolean } $1 . boundaryClass Whether or not to apply a boundary
* class .
* @ param { boolean } $1 . isEditableTree
2021-07-14 01:58:30 +02:00
*
2021-11-08 15:29:21 +01:00
* @ return { Object } Information to be used for element creation .
2019-03-07 10:09:59 +01:00
* /
2021-07-14 01:58:30 +02:00
2023-06-27 16:24:19 +02:00
function fromFormat ( {
type ,
tagName ,
attributes ,
unregisteredAttributes ,
object ,
boundaryClass ,
isEditableTree
} ) {
2021-05-19 17:09:27 +02:00
const formatType = get _format _type _getFormatType ( type ) ;
let elementAttributes = { } ;
2019-03-07 10:09:59 +01:00
2023-07-11 08:59:09 +02:00
if ( boundaryClass && isEditableTree ) {
2019-03-07 10:09:59 +01:00
elementAttributes [ 'data-rich-text-format-boundary' ] = 'true' ;
}
2018-12-14 12:02:53 +01:00
2018-12-18 04:14:52 +01:00
if ( ! formatType ) {
2019-03-07 10:09:59 +01:00
if ( attributes ) {
2021-05-19 17:09:27 +02:00
elementAttributes = { ... attributes ,
... elementAttributes
} ;
2019-03-07 10:09:59 +01:00
}
2018-12-18 04:14:52 +01:00
return {
2021-05-19 17:09:27 +02:00
type ,
2021-07-14 01:58:30 +02:00
attributes : restoreOnAttributes ( elementAttributes , isEditableTree ) ,
2021-05-19 17:09:27 +02:00
object
2018-12-18 04:14:52 +01:00
} ;
}
2018-12-14 12:02:53 +01:00
2021-05-19 17:09:27 +02:00
elementAttributes = { ... unregisteredAttributes ,
... elementAttributes
} ;
2018-12-14 12:02:53 +01:00
2021-05-19 17:09:27 +02:00
for ( const name in attributes ) {
const key = formatType . attributes ? formatType . attributes [ name ] : false ;
2018-12-14 12:02:53 +01:00
2018-12-18 04:14:52 +01:00
if ( key ) {
elementAttributes [ key ] = attributes [ name ] ;
} else {
elementAttributes [ name ] = attributes [ name ] ;
}
}
2018-12-14 12:02:53 +01:00
2018-12-18 04:14:52 +01:00
if ( formatType . className ) {
if ( elementAttributes . class ) {
2021-05-19 17:09:27 +02:00
elementAttributes . class = ` ${ formatType . className } ${ elementAttributes . class } ` ;
2018-12-18 04:14:52 +01:00
} else {
elementAttributes . class = formatType . className ;
}
2023-06-27 16:24:19 +02:00
} // When a format is declared as non editable, make it non editable in the
// editor.
if ( isEditableTree && formatType . contentEditable === false ) {
elementAttributes . contenteditable = 'false' ;
2018-12-18 04:14:52 +01:00
}
2018-12-14 12:02:53 +01:00
2018-12-18 04:14:52 +01:00
return {
2023-07-11 08:59:09 +02:00
type : tagName || formatType . tagName ,
2018-12-18 04:14:52 +01:00
object : formatType . object ,
2021-07-14 01:58:30 +02:00
attributes : restoreOnAttributes ( elementAttributes , isEditableTree )
2018-12-18 04:14:52 +01:00
} ;
}
2020-01-22 23:06:21 +01:00
/ * *
* Checks if both arrays of formats up until a certain index are equal .
*
* @ param { Array } a Array of formats to compare .
* @ param { Array } b Array of formats to compare .
* @ param { number } index Index to check until .
* /
function isEqualUntil ( a , b , index ) {
do {
if ( a [ index ] !== b [ index ] ) {
return false ;
}
} while ( index -- ) ;
return true ;
}
2018-12-14 12:02:53 +01:00
2023-06-27 16:24:19 +02:00
function toTree ( {
value ,
multilineTag ,
preserveWhiteSpace ,
createEmpty ,
append ,
getLastChild ,
getParent ,
isText ,
getText ,
remove ,
appendText ,
onStartIndex ,
onEndIndex ,
isEditableTree ,
placeholder
} ) {
2021-05-19 17:09:27 +02:00
const {
formats ,
replacements ,
text ,
start ,
end
} = value ;
const formatsLength = formats . length + 1 ;
const tree = createEmpty ( ) ;
const multilineFormat = {
2018-12-18 04:14:52 +01:00
type : multilineTag
} ;
2021-05-19 17:09:27 +02:00
const activeFormats = getActiveFormats ( value ) ;
const deepestActiveFormat = activeFormats [ activeFormats . length - 1 ] ;
let lastSeparatorFormats ;
let lastCharacterFormats ;
let lastCharacter ; // If we're building a multiline tree, start off with a multiline element.
2018-12-14 12:02:53 +01:00
2018-12-18 04:14:52 +01:00
if ( multilineTag ) {
append ( append ( tree , {
type : multilineTag
} ) , '' ) ;
lastCharacterFormats = lastSeparatorFormats = [ multilineFormat ] ;
} else {
append ( tree , '' ) ;
}
2018-12-14 12:02:53 +01:00
2021-05-19 17:09:27 +02:00
for ( let i = 0 ; i < formatsLength ; i ++ ) {
const character = text . charAt ( i ) ;
const shouldInsertPadding = isEditableTree && ( // Pad the line if the line is empty.
2019-03-21 13:48:00 +01:00
! lastCharacter || lastCharacter === LINE _SEPARATOR || // Pad the line if the previous character is a line break, otherwise
// the line break won't be visible.
lastCharacter === '\n' ) ;
2021-05-19 17:09:27 +02:00
let characterFormats = formats [ i ] ; // Set multiline tags in queue for building the tree.
2018-12-14 12:02:53 +01:00
2018-12-18 04:14:52 +01:00
if ( multilineTag ) {
if ( character === LINE _SEPARATOR ) {
2021-05-19 17:09:27 +02:00
characterFormats = lastSeparatorFormats = ( replacements [ i ] || [ ] ) . reduce ( ( accumulator , format ) => {
2019-03-21 13:48:00 +01:00
accumulator . push ( format , multilineFormat ) ;
2018-12-18 04:14:52 +01:00
return accumulator ;
} , [ multilineFormat ] ) ;
} else {
2021-05-19 17:09:27 +02:00
characterFormats = [ ... lastSeparatorFormats , ... ( characterFormats || [ ] ) ] ;
2018-12-18 04:14:52 +01:00
}
}
2018-12-14 12:02:53 +01:00
2021-05-19 17:09:27 +02:00
let pointer = getLastChild ( tree ) ;
2018-12-14 12:02:53 +01:00
2019-03-21 13:48:00 +01:00
if ( shouldInsertPadding && character === LINE _SEPARATOR ) {
2021-05-19 17:09:27 +02:00
let node = pointer ;
2018-12-14 12:02:53 +01:00
2018-12-18 04:14:52 +01:00
while ( ! isText ( node ) ) {
node = getLastChild ( node ) ;
}
2018-12-17 05:52:00 +01:00
2019-09-19 17:19:18 +02:00
append ( getParent ( node ) , ZWNBSP ) ;
2019-03-21 13:48:00 +01:00
} // Set selection for the start of line.
if ( lastCharacter === LINE _SEPARATOR ) {
2021-05-19 17:09:27 +02:00
let node = pointer ;
2019-03-21 13:48:00 +01:00
2021-05-19 17:09:27 +02:00
while ( ! isText ( node ) ) {
node = getLastChild ( node ) ;
2019-03-21 13:48:00 +01:00
}
2018-12-18 04:14:52 +01:00
if ( onStartIndex && start === i ) {
2021-05-19 17:09:27 +02:00
onStartIndex ( tree , node ) ;
2018-12-18 04:14:52 +01:00
}
2018-12-14 12:02:53 +01:00
2018-12-18 04:14:52 +01:00
if ( onEndIndex && end === i ) {
2021-05-19 17:09:27 +02:00
onEndIndex ( tree , node ) ;
2018-12-18 04:14:52 +01:00
}
}
2018-12-14 12:02:53 +01:00
2018-12-18 04:14:52 +01:00
if ( characterFormats ) {
2021-05-19 17:09:27 +02:00
characterFormats . forEach ( ( format , formatIndex ) => {
2020-01-22 23:06:21 +01:00
if ( pointer && lastCharacterFormats && // Reuse the last element if all formats remain the same.
isEqualUntil ( characterFormats , lastCharacterFormats , formatIndex ) && ( // Do not reuse the last element if the character is a
2018-12-18 04:14:52 +01:00
// line separator.
character !== LINE _SEPARATOR || characterFormats . length - 1 !== formatIndex ) ) {
pointer = getLastChild ( pointer ) ;
return ;
}
2018-12-17 05:52:00 +01:00
2021-05-19 17:09:27 +02:00
const {
type ,
2023-02-07 08:04:52 +01:00
tagName ,
2021-05-19 17:09:27 +02:00
attributes ,
unregisteredAttributes
} = format ;
const boundaryClass = isEditableTree && character !== LINE _SEPARATOR && format === deepestActiveFormat ;
const parent = getParent ( pointer ) ;
const newNode = append ( parent , fromFormat ( {
type ,
2023-02-07 08:04:52 +01:00
tagName ,
2021-05-19 17:09:27 +02:00
attributes ,
unregisteredAttributes ,
2021-07-14 01:58:30 +02:00
boundaryClass ,
isEditableTree
2019-03-07 10:09:59 +01:00
} ) ) ;
2018-12-17 05:52:00 +01:00
2018-12-18 04:14:52 +01:00
if ( isText ( pointer ) && getText ( pointer ) . length === 0 ) {
remove ( pointer ) ;
}
2019-03-21 13:48:00 +01:00
pointer = append ( newNode , '' ) ;
2018-12-18 04:14:52 +01:00
} ) ;
} // No need for further processing if the character is a line separator.
if ( character === LINE _SEPARATOR ) {
lastCharacterFormats = characterFormats ;
lastCharacter = character ;
2021-05-19 17:09:27 +02:00
continue ;
2019-03-07 10:09:59 +01:00
} // If there is selection at 0, handle it before characters are inserted.
2018-12-18 04:14:52 +01:00
if ( i === 0 ) {
if ( onStartIndex && start === 0 ) {
onStartIndex ( tree , pointer ) ;
}
if ( onEndIndex && end === 0 ) {
onEndIndex ( tree , pointer ) ;
}
}
2019-03-21 13:48:00 +01:00
if ( character === OBJECT _REPLACEMENT _CHARACTER ) {
2023-06-27 16:24:19 +02:00
const replacement = replacements [ i ] ;
if ( ! replacement ) continue ;
const {
type ,
attributes ,
innerHTML
} = replacement ;
const formatType = get _format _type _getFormatType ( type ) ;
2021-11-08 15:29:21 +01:00
2023-06-27 16:24:19 +02:00
if ( ! isEditableTree && type === 'script' ) {
2021-07-14 01:58:30 +02:00
pointer = append ( getParent ( pointer ) , fromFormat ( {
type : 'script' ,
isEditableTree
} ) ) ;
append ( pointer , {
2023-06-27 16:24:19 +02:00
html : decodeURIComponent ( attributes [ 'data-rich-text-script' ] )
2021-07-14 01:58:30 +02:00
} ) ;
2023-06-27 16:24:19 +02:00
} else if ( formatType ? . contentEditable === false ) {
// For non editable formats, render the stored inner HTML.
pointer = append ( getParent ( pointer ) , fromFormat ( { ... replacement ,
isEditableTree ,
boundaryClass : start === i && end === i + 1
} ) ) ;
2023-07-11 08:59:09 +02:00
if ( innerHTML ) {
append ( pointer , {
html : innerHTML
} ) ;
}
2021-07-14 01:58:30 +02:00
} else {
2023-06-27 16:24:19 +02:00
pointer = append ( getParent ( pointer ) , fromFormat ( { ... replacement ,
2021-07-14 01:58:30 +02:00
object : true ,
isEditableTree
} ) ) ;
} // Ensure pointer is text node.
2019-03-21 13:48:00 +01:00
pointer = append ( getParent ( pointer ) , '' ) ;
2020-01-08 12:57:23 +01:00
} else if ( ! preserveWhiteSpace && character === '\n' ) {
2019-03-21 13:48:00 +01:00
pointer = append ( getParent ( pointer ) , {
type : 'br' ,
attributes : isEditableTree ? {
'data-rich-text-line-break' : 'true'
} : undefined ,
object : true
} ) ; // Ensure pointer is text node.
pointer = append ( getParent ( pointer ) , '' ) ;
} else if ( ! isText ( pointer ) ) {
pointer = append ( getParent ( pointer ) , character ) ;
} else {
appendText ( pointer , character ) ;
2018-12-18 04:14:52 +01:00
}
if ( onStartIndex && start === i + 1 ) {
onStartIndex ( tree , pointer ) ;
}
2018-12-17 05:52:00 +01:00
2018-12-18 04:14:52 +01:00
if ( onEndIndex && end === i + 1 ) {
onEndIndex ( tree , pointer ) ;
2018-12-17 05:52:00 +01:00
}
2019-03-21 13:48:00 +01:00
if ( shouldInsertPadding && i === text . length ) {
2019-09-19 17:19:18 +02:00
append ( getParent ( pointer ) , ZWNBSP ) ;
if ( placeholder && text . length === 0 ) {
append ( getParent ( pointer ) , {
type : 'span' ,
attributes : {
'data-rich-text-placeholder' : placeholder ,
// Necessary to prevent the placeholder from catching
// selection. The placeholder is also not editable after
// all.
2021-04-15 17:19:43 +02:00
contenteditable : 'false' ,
style : 'pointer-events:none;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;'
2019-09-19 17:19:18 +02:00
}
} ) ;
}
2019-03-21 13:48:00 +01:00
}
2018-12-18 04:14:52 +01:00
lastCharacterFormats = characterFormats ;
lastCharacter = character ;
}
2018-12-14 05:41:57 +01:00
2018-12-18 04:14:52 +01:00
return tree ;
}
2018-12-14 05:41:57 +01:00
2023-06-27 16:24:19 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/is-range-equal.js
/ * *
* Returns true if two ranges are equal , or false otherwise . Ranges are
* considered equal if their start and end occur in the same container and
* offset .
*
* @ param { Range | null } a First range object to test .
* @ param { Range | null } b First range object to test .
*
* @ return { boolean } Whether the two ranges are equal .
* /
function isRangeEqual ( a , b ) {
return a === b || a && b && a . startContainer === b . startContainer && a . startOffset === b . startOffset && a . endContainer === b . endContainer && a . endOffset === b . endOffset ;
}
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/to-dom.js
2018-12-14 05:41:57 +01:00
/ * *
* Internal dependencies
* /
2018-12-19 04:16:48 +01:00
2023-06-27 16:24:19 +02:00
/** @typedef {import('./types').RichTextValue} RichTextValue */
2020-10-13 15:10:30 +02:00
2018-12-14 05:41:57 +01:00
/ * *
* Creates a path as an array of indices from the given root node to the given
* node .
*
* @ param { Node } node Node to find the path of .
* @ param { HTMLElement } rootNode Root node to find the path from .
* @ param { Array } path Initial path to build on .
*
* @ return { Array } The path from the root node to the node .
* /
function createPathToNode ( node , rootNode , path ) {
2021-05-19 17:09:27 +02:00
const parentNode = node . parentNode ;
let i = 0 ;
2018-12-14 05:41:57 +01:00
while ( node = node . previousSibling ) {
i ++ ;
}
2021-05-19 17:09:27 +02:00
path = [ i , ... path ] ;
2018-12-14 05:41:57 +01:00
if ( parentNode !== rootNode ) {
path = createPathToNode ( parentNode , rootNode , path ) ;
}
return path ;
}
/ * *
* Gets a node given a path ( array of indices ) from the given node .
*
* @ param { HTMLElement } node Root node to find the wanted node in .
* @ param { Array } path Path ( indices ) to the wanted node .
*
* @ return { Object } Object with the found node and the remaining offset ( if any ) .
* /
function getNodeByPath ( node , path ) {
2021-05-19 17:09:27 +02:00
path = [ ... path ] ;
2018-12-14 05:41:57 +01:00
while ( node && path . length > 1 ) {
node = node . childNodes [ path . shift ( ) ] ;
}
return {
2021-05-19 17:09:27 +02:00
node ,
2018-12-14 05:41:57 +01:00
offset : path [ 0 ]
} ;
}
2022-04-11 14:04:30 +02:00
function append ( element , child ) {
2023-07-11 08:59:09 +02:00
if ( child . html !== undefined ) {
return element . innerHTML += child . html ;
}
2018-12-14 05:41:57 +01:00
if ( typeof child === 'string' ) {
child = element . ownerDocument . createTextNode ( child ) ;
}
2021-05-19 17:09:27 +02:00
const {
type ,
attributes
} = child ;
2018-12-14 05:41:57 +01:00
if ( type ) {
child = element . ownerDocument . createElement ( type ) ;
2021-05-19 17:09:27 +02:00
for ( const key in attributes ) {
2018-12-14 05:41:57 +01:00
child . setAttribute ( key , attributes [ key ] ) ;
}
}
return element . appendChild ( child ) ;
}
2022-04-11 14:04:30 +02:00
function appendText ( node , text ) {
2018-12-14 05:41:57 +01:00
node . appendData ( text ) ;
}
2023-06-27 16:24:19 +02:00
function getLastChild ( {
lastChild
} ) {
2018-12-14 05:41:57 +01:00
return lastChild ;
}
2023-06-27 16:24:19 +02:00
function getParent ( {
parentNode
} ) {
2018-12-14 05:41:57 +01:00
return parentNode ;
}
2022-04-11 14:04:30 +02:00
function isText ( node ) {
2020-06-26 15:33:47 +02:00
return node . nodeType === node . TEXT _NODE ;
2018-12-14 05:41:57 +01:00
}
2023-06-27 16:24:19 +02:00
function getText ( {
nodeValue
} ) {
2018-12-14 05:41:57 +01:00
return nodeValue ;
}
2018-12-18 04:14:52 +01:00
function to _dom _remove ( node ) {
2018-12-14 05:41:57 +01:00
return node . parentNode . removeChild ( node ) ;
}
2023-06-27 16:24:19 +02:00
function toDom ( {
value ,
multilineTag ,
prepareEditableTree ,
isEditableTree = true ,
placeholder ,
doc = document
} ) {
2021-05-19 17:09:27 +02:00
let startPath = [ ] ;
let endPath = [ ] ;
2019-09-19 17:19:18 +02:00
if ( prepareEditableTree ) {
2021-05-19 17:09:27 +02:00
value = { ... value ,
2019-09-19 17:19:18 +02:00
formats : prepareEditableTree ( value )
2021-05-19 17:09:27 +02:00
} ;
2019-09-19 17:19:18 +02:00
}
2020-06-26 15:33:47 +02:00
/ * *
* Returns a new instance of a DOM tree upon which RichText operations can be
* applied .
*
* Note : The current implementation will return a shared reference , reset on
* each call to ` createEmpty ` . Therefore , you should not hold a reference to
* the value to operate upon asynchronously , as it may have unexpected results .
*
* @ return { Object } RichText tree .
* /
2021-05-19 17:09:27 +02:00
const createEmpty = ( ) => createElement ( doc , '' ) ;
2019-09-19 17:19:18 +02:00
2021-05-19 17:09:27 +02:00
const tree = toTree ( {
value ,
multilineTag ,
createEmpty ,
2022-04-11 14:04:30 +02:00
append ,
getLastChild ,
getParent ,
isText ,
getText ,
2018-12-18 04:14:52 +01:00
remove : to _dom _remove ,
2022-04-11 14:04:30 +02:00
appendText ,
2021-05-19 17:09:27 +02:00
onStartIndex ( body , pointer ) {
2018-12-14 05:41:57 +01:00
startPath = createPathToNode ( pointer , body , [ pointer . nodeValue . length ] ) ;
} ,
2021-05-19 17:09:27 +02:00
onEndIndex ( body , pointer ) {
2018-12-14 05:41:57 +01:00
endPath = createPathToNode ( pointer , body , [ pointer . nodeValue . length ] ) ;
} ,
2021-05-19 17:09:27 +02:00
isEditableTree ,
placeholder
2018-12-14 05:41:57 +01:00
} ) ;
return {
body : tree ,
selection : {
2021-05-19 17:09:27 +02:00
startPath ,
endPath
2018-12-14 05:41:57 +01:00
}
} ;
}
/ * *
* Create an ` Element ` tree from a Rich Text value and applies the difference to
* the ` Element ` tree contained by ` current ` . If a ` multilineTag ` is provided ,
* text separated by two new lines will be wrapped in an ` Element ` of that type .
*
2020-10-13 15:10:30 +02:00
* @ param { Object } $1 Named arguments .
* @ param { RichTextValue } $1 . value Value to apply .
* @ param { HTMLElement } $1 . current The live root node to apply the element tree to .
* @ param { string } [ $1 . multilineTag ] Multiline tag .
* @ param { Function } [ $1 . prepareEditableTree ] Function to filter editorable formats .
* @ param { boolean } [ $1 . _ _unstableDomOnly ] Only apply elements , no selection .
* @ param { string } [ $1 . placeholder ] Placeholder text .
2018-12-14 05:41:57 +01:00
* /
2023-06-27 16:24:19 +02:00
function apply ( {
value ,
current ,
multilineTag ,
prepareEditableTree ,
_ _unstableDomOnly ,
placeholder
} ) {
2018-12-14 05:41:57 +01:00
// Construct a new element tree in memory.
2021-05-19 17:09:27 +02:00
const {
body ,
selection
} = toDom ( {
value ,
multilineTag ,
prepareEditableTree ,
placeholder ,
2020-06-26 15:33:47 +02:00
doc : current . ownerDocument
2021-05-19 17:09:27 +02:00
} ) ;
2018-12-14 05:41:57 +01:00
applyValue ( body , current ) ;
2019-03-07 10:09:59 +01:00
if ( value . start !== undefined && ! _ _unstableDomOnly ) {
2018-12-14 05:41:57 +01:00
applySelection ( selection , current ) ;
}
}
function applyValue ( future , current ) {
2021-05-19 17:09:27 +02:00
let i = 0 ;
let futureChild ;
2018-12-14 05:41:57 +01:00
2018-12-19 04:16:48 +01:00
while ( futureChild = future . firstChild ) {
2021-05-19 17:09:27 +02:00
const currentChild = current . childNodes [ i ] ;
2018-12-14 05:41:57 +01:00
if ( ! currentChild ) {
2018-12-19 04:16:48 +01:00
current . appendChild ( futureChild ) ;
} else if ( ! currentChild . isEqualNode ( futureChild ) ) {
2020-06-26 15:33:47 +02:00
if ( currentChild . nodeName !== futureChild . nodeName || currentChild . nodeType === currentChild . TEXT _NODE && currentChild . data !== futureChild . data ) {
2019-03-07 10:09:59 +01:00
current . replaceChild ( futureChild , currentChild ) ;
} else {
2021-05-19 17:09:27 +02:00
const currentAttributes = currentChild . attributes ;
const futureAttributes = futureChild . attributes ;
2019-03-07 10:09:59 +01:00
if ( currentAttributes ) {
2021-05-19 17:09:27 +02:00
let ii = currentAttributes . length ; // Reverse loop because `removeAttribute` on `currentChild`
2019-09-19 17:19:18 +02:00
// changes `currentAttributes`.
while ( ii -- ) {
2021-05-19 17:09:27 +02:00
const {
name
} = currentAttributes [ ii ] ;
2019-03-07 10:09:59 +01:00
if ( ! futureChild . getAttribute ( name ) ) {
currentChild . removeAttribute ( name ) ;
}
}
}
if ( futureAttributes ) {
2021-05-19 17:09:27 +02:00
for ( let ii = 0 ; ii < futureAttributes . length ; ii ++ ) {
const {
name ,
value
} = futureAttributes [ ii ] ;
if ( currentChild . getAttribute ( name ) !== value ) {
currentChild . setAttribute ( name , value ) ;
2019-03-07 10:09:59 +01:00
}
}
}
applyValue ( futureChild , currentChild ) ;
future . removeChild ( futureChild ) ;
}
2018-12-14 05:41:57 +01:00
} else {
2018-12-19 04:16:48 +01:00
future . removeChild ( futureChild ) ;
2018-12-14 05:41:57 +01:00
}
i ++ ;
}
while ( current . childNodes [ i ] ) {
current . removeChild ( current . childNodes [ i ] ) ;
}
}
2023-06-27 16:24:19 +02:00
function applySelection ( {
startPath ,
endPath
} , current ) {
2021-05-19 17:09:27 +02:00
const {
node : startContainer ,
offset : startOffset
} = getNodeByPath ( current , startPath ) ;
const {
node : endContainer ,
offset : endOffset
} = getNodeByPath ( current , endPath ) ;
const {
ownerDocument
} = current ;
const {
defaultView
} = ownerDocument ;
const selection = defaultView . getSelection ( ) ;
const range = ownerDocument . createRange ( ) ;
2019-03-07 10:09:59 +01:00
range . setStart ( startContainer , startOffset ) ;
2020-02-06 22:03:31 +01:00
range . setEnd ( endContainer , endOffset ) ;
2021-05-19 17:09:27 +02:00
const {
activeElement
} = ownerDocument ;
2018-12-14 05:41:57 +01:00
2019-03-07 10:09:59 +01:00
if ( selection . rangeCount > 0 ) {
2018-12-19 04:16:48 +01:00
// If the to be added range and the live range are the same, there's no
// need to remove the live range and add the equivalent range.
2019-03-07 10:09:59 +01:00
if ( isRangeEqual ( range , selection . getRangeAt ( 0 ) ) ) {
2018-12-19 04:16:48 +01:00
return ;
}
2019-03-07 10:09:59 +01:00
selection . removeAllRanges ( ) ;
2018-12-19 04:16:48 +01:00
}
2020-03-03 00:21:15 +01:00
selection . addRange ( range ) ; // This function is not intended to cause a shift in focus. Since the above
// selection manipulations may shift focus, ensure that focus is restored to
2020-03-24 00:40:19 +01:00
// its previous state.
2020-03-03 00:21:15 +01:00
2020-06-26 15:33:47 +02:00
if ( activeElement !== ownerDocument . activeElement ) {
2020-03-03 00:21:15 +01:00
// The `instanceof` checks protect against edge cases where the focused
// element is not of the interface HTMLElement (does not have a `focus`
// or `blur` property).
//
// See: https://github.com/Microsoft/TypeScript/issues/5901#issuecomment-431649653
2020-06-26 15:33:47 +02:00
if ( activeElement instanceof defaultView . HTMLElement ) {
2020-03-24 00:40:19 +01:00
activeElement . focus ( ) ;
2020-03-03 00:21:15 +01:00
}
}
2018-12-14 05:41:57 +01:00
}
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: external ["wp","escapeHtml"]
var external _wp _escapeHtml _namespaceObject = window [ "wp" ] [ "escapeHtml" ] ;
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/to-html-string.js
2018-12-14 05:41:57 +01:00
/ * *
2019-03-07 10:09:59 +01:00
* WordPress dependencies
2018-12-14 05:41:57 +01:00
* /
/ * *
* Internal dependencies
* /
2023-06-27 16:24:19 +02:00
/** @typedef {import('./types').RichTextValue} RichTextValue */
2020-10-13 15:10:30 +02:00
2018-12-14 05:41:57 +01:00
/ * *
* Create an HTML string from a Rich Text value . If a ` multilineTag ` is
2018-12-15 12:00:40 +01:00
* provided , text separated by a line separator will be wrapped in it .
2018-12-14 05:41:57 +01:00
*
2020-10-13 15:10:30 +02:00
* @ param { Object } $1 Named argements .
* @ param { RichTextValue } $1 . value Rich text value .
* @ param { string } [ $1 . multilineTag ] Multiline tag .
* @ param { boolean } [ $1 . preserveWhiteSpace ] Whether or not to use newline
* characters for line breaks .
2018-12-14 05:41:57 +01:00
*
* @ return { string } HTML string .
* /
2023-06-27 16:24:19 +02:00
function toHTMLString ( {
value ,
multilineTag ,
preserveWhiteSpace
} ) {
2021-05-19 17:09:27 +02:00
const tree = toTree ( {
value ,
multilineTag ,
preserveWhiteSpace ,
2022-04-11 14:04:30 +02:00
createEmpty ,
2018-12-18 04:14:52 +01:00
append : to _html _string _append ,
getLastChild : to _html _string _getLastChild ,
getParent : to _html _string _getParent ,
isText : to _html _string _isText ,
getText : to _html _string _getText ,
remove : to _html _string _remove ,
appendText : to _html _string _appendText
2018-12-14 05:41:57 +01:00
} ) ;
return createChildrenHTML ( tree . children ) ;
}
2022-04-11 14:04:30 +02:00
function createEmpty ( ) {
2018-12-15 12:00:40 +01:00
return { } ;
2018-12-14 05:41:57 +01:00
}
2023-06-27 16:24:19 +02:00
function to _html _string _getLastChild ( {
children
} ) {
2018-12-14 05:41:57 +01:00
return children && children [ children . length - 1 ] ;
}
2018-12-18 04:14:52 +01:00
function to _html _string _append ( parent , object ) {
2018-12-14 05:41:57 +01:00
if ( typeof object === 'string' ) {
object = {
text : object
} ;
}
object . parent = parent ;
parent . children = parent . children || [ ] ;
parent . children . push ( object ) ;
return object ;
}
2018-12-18 04:14:52 +01:00
function to _html _string _appendText ( object , text ) {
2018-12-14 05:41:57 +01:00
object . text += text ;
}
2023-06-27 16:24:19 +02:00
function to _html _string _getParent ( {
parent
} ) {
2018-12-14 05:41:57 +01:00
return parent ;
}
2023-06-27 16:24:19 +02:00
function to _html _string _isText ( {
text
} ) {
2018-12-14 05:41:57 +01:00
return typeof text === 'string' ;
}
2023-06-27 16:24:19 +02:00
function to _html _string _getText ( {
text
} ) {
2018-12-14 05:41:57 +01:00
return text ;
}
2018-12-18 04:14:52 +01:00
function to _html _string _remove ( object ) {
2021-05-19 17:09:27 +02:00
const index = object . parent . children . indexOf ( object ) ;
2018-12-14 05:41:57 +01:00
if ( index !== - 1 ) {
object . parent . children . splice ( index , 1 ) ;
}
return object ;
}
2023-06-27 16:24:19 +02:00
function createElementHTML ( {
type ,
attributes ,
object ,
children
} ) {
2021-05-19 17:09:27 +02:00
let attributeString = '' ;
2018-12-14 05:41:57 +01:00
2021-05-19 17:09:27 +02:00
for ( const key in attributes ) {
2022-04-11 14:04:30 +02:00
if ( ! ( 0 , external _wp _escapeHtml _namespaceObject . isValidAttributeName ) ( key ) ) {
2018-12-14 05:53:54 +01:00
continue ;
}
2022-04-11 14:04:30 +02:00
attributeString += ` ${ key } =" ${ ( 0 , external _wp _escapeHtml _namespaceObject . escapeAttribute ) ( attributes [ key ] ) } " ` ;
2018-12-14 05:41:57 +01:00
}
if ( object ) {
2021-05-19 17:09:27 +02:00
return ` < ${ type } ${ attributeString } > ` ;
2018-12-14 05:41:57 +01:00
}
2021-05-19 17:09:27 +02:00
return ` < ${ type } ${ attributeString } > ${ createChildrenHTML ( children ) } </ ${ type } > ` ;
2018-12-14 05:41:57 +01:00
}
2023-06-27 16:24:19 +02:00
function createChildrenHTML ( children = [ ] ) {
2021-05-19 17:09:27 +02:00
return children . map ( child => {
2021-07-14 01:58:30 +02:00
if ( child . html !== undefined ) {
return child . html ;
}
2022-04-11 14:04:30 +02:00
return child . text === undefined ? createElementHTML ( child ) : ( 0 , external _wp _escapeHtml _namespaceObject . escapeEditableHTML ) ( child . text ) ;
2018-12-18 04:14:52 +01:00
} ) . join ( '' ) ;
}
2018-12-14 12:02:53 +01:00
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: external ["wp","a11y"]
var external _wp _a11y _namespaceObject = window [ "wp" ] [ "a11y" ] ;
; // CONCATENATED MODULE: external ["wp","i18n"]
var external _wp _i18n _namespaceObject = window [ "wp" ] [ "i18n" ] ;
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/toggle-format.js
2021-11-08 15:29:21 +01:00
/ * *
* WordPress dependencies
* /
2018-12-14 12:02:53 +01:00
/ * *
* Internal dependencies
* /
2021-11-08 15:29:21 +01:00
2023-06-27 16:24:19 +02:00
/** @typedef {import('./types').RichTextValue} RichTextValue */
2020-10-13 15:10:30 +02:00
2023-06-27 16:24:19 +02:00
/** @typedef {import('./types').RichTextFormat} RichTextFormat */
2020-10-13 15:10:30 +02:00
2018-12-14 12:02:53 +01:00
/ * *
* Toggles a format object to a Rich Text value at the current selection .
*
2020-10-13 15:10:30 +02:00
* @ param { RichTextValue } value Value to modify .
* @ param { RichTextFormat } format Format to apply or remove .
2018-12-14 12:02:53 +01:00
*
2020-10-13 15:10:30 +02:00
* @ return { RichTextValue } A new value with the format applied or removed .
2018-12-14 12:02:53 +01:00
* /
function toggleFormat ( value , format ) {
2018-12-18 04:14:52 +01:00
if ( getActiveFormat ( value , format . type ) ) {
2021-11-08 15:29:21 +01:00
// For screen readers, will announce if formatting control is disabled.
if ( format . title ) {
// translators: %s: title of the formatting control
2022-04-11 14:04:30 +02:00
( 0 , external _wp _a11y _namespaceObject . speak ) ( ( 0 , external _wp _i18n _namespaceObject . sprintf ) ( ( 0 , external _wp _i18n _namespaceObject . _ _ ) ( '%s removed.' ) , format . title ) , 'assertive' ) ;
2021-11-08 15:29:21 +01:00
}
2018-12-18 04:14:52 +01:00
return removeFormat ( value , format . type ) ;
2021-11-08 15:29:21 +01:00
} // For screen readers, will announce if formatting control is enabled.
if ( format . title ) {
// translators: %s: title of the formatting control
2022-04-11 14:04:30 +02:00
( 0 , external _wp _a11y _namespaceObject . speak ) ( ( 0 , external _wp _i18n _namespaceObject . sprintf ) ( ( 0 , external _wp _i18n _namespaceObject . _ _ ) ( '%s applied.' ) , format . title ) , 'assertive' ) ;
2018-12-14 12:02:53 +01:00
}
2020-01-08 12:57:23 +01:00
return applyFormat ( value , format ) ;
}
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/unregister-format-type.js
2020-01-08 12:57:23 +01:00
/ * *
* WordPress dependencies
* /
2021-01-28 03:04:13 +01:00
/ * *
* Internal dependencies
* /
2023-06-27 16:24:19 +02:00
/** @typedef {import('./register-format-type').WPFormat} WPFormat */
2020-01-08 12:57:23 +01:00
/ * *
* Unregisters a format .
*
* @ param { string } name Format name .
*
2023-06-27 16:24:19 +02:00
* @ return { WPFormat | undefined } The previous format value , if it has
2020-10-13 15:10:30 +02:00
* been successfully unregistered ;
* otherwise ` undefined ` .
2020-01-08 12:57:23 +01:00
* /
function unregisterFormatType ( name ) {
2022-04-11 14:04:30 +02:00
const oldFormat = ( 0 , external _wp _data _namespaceObject . select ) ( store ) . getFormatType ( name ) ;
2020-01-08 12:57:23 +01:00
if ( ! oldFormat ) {
2021-05-19 17:09:27 +02:00
window . console . error ( ` Format ${ name } is not registered. ` ) ;
2020-01-08 12:57:23 +01:00
return ;
}
2022-04-11 14:04:30 +02:00
( 0 , external _wp _data _namespaceObject . dispatch ) ( store ) . removeFormatTypes ( name ) ;
2020-01-08 12:57:23 +01:00
return oldFormat ;
}
2022-09-20 17:43:29 +02:00
; // CONCATENATED MODULE: external ["wp","element"]
var external _wp _element _namespaceObject = window [ "wp" ] [ "element" ] ;
; // CONCATENATED MODULE: external ["wp","deprecated"]
var external _wp _deprecated _namespaceObject = window [ "wp" ] [ "deprecated" ] ;
var external _wp _deprecated _default = /*#__PURE__*/ _ _webpack _require _ _ . n ( external _wp _deprecated _namespaceObject ) ;
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/use-anchor-ref.js
2020-01-08 12:57:23 +01:00
/ * *
2022-09-20 17:43:29 +02:00
* WordPress dependencies
2020-01-08 12:57:23 +01:00
* /
2020-10-13 15:10:30 +02:00
2020-01-08 12:57:23 +01:00
/ * *
2022-09-20 17:43:29 +02:00
* Internal dependencies
2020-01-08 12:57:23 +01:00
* /
2023-06-27 16:24:19 +02:00
/ * *
* @ template T
* @ typedef { import ( '@wordpress/element' ) . RefObject < T > } RefObject < T >
* /
2018-12-14 12:02:53 +01:00
2023-06-27 16:24:19 +02:00
/** @typedef {import('../register-format-type').WPFormat} WPFormat */
2018-12-14 12:02:53 +01:00
2023-06-27 16:24:19 +02:00
/** @typedef {import('../types').RichTextValue} RichTextValue */
2020-10-13 15:10:30 +02:00
2018-12-14 12:02:53 +01:00
/ * *
2022-09-20 17:43:29 +02:00
* This hook , to be used in a format type ' s Edit component , returns the active
* element that is formatted , or the selection range if no format is active .
* The returned value is meant to be used for positioning UI , e . g . by passing it
* to the ` Popover ` component .
2018-12-14 12:02:53 +01:00
*
2022-09-20 17:43:29 +02:00
* @ param { Object } $1 Named parameters .
* @ param { RefObject < HTMLElement > } $1 . ref React ref of the element
* containing the editable content .
* @ param { RichTextValue } $1 . value Value to check for selection .
2023-06-27 16:24:19 +02:00
* @ param { WPFormat } $1 . settings The format type ' s settings .
2018-12-14 12:02:53 +01:00
*
2022-09-20 17:43:29 +02:00
* @ return { Element | Range } The active element or selection range .
2018-12-14 12:02:53 +01:00
* /
2023-06-27 16:24:19 +02:00
function useAnchorRef ( {
ref ,
value ,
settings = { }
} ) {
2022-09-20 17:43:29 +02:00
external _wp _deprecated _default ( ) ( '`useAnchorRef` hook' , {
since : '6.1' ,
alternative : '`useAnchor` hook'
} ) ;
2021-05-19 17:09:27 +02:00
const {
2022-09-20 17:43:29 +02:00
tagName ,
className ,
name
} = settings ;
const activeFormat = name ? getActiveFormat ( value , name ) : undefined ;
return ( 0 , external _wp _element _namespaceObject . useMemo ) ( ( ) => {
if ( ! ref . current ) return ;
const {
ownerDocument : {
defaultView
}
} = ref . current ;
const selection = defaultView . getSelection ( ) ;
if ( ! selection . rangeCount ) {
return ;
}
const range = selection . getRangeAt ( 0 ) ;
if ( ! activeFormat ) {
return range ;
}
let element = range . startContainer ; // If the caret is right before the element, select the next element.
element = element . nextElementSibling || element ;
while ( element . nodeType !== element . ELEMENT _NODE ) {
element = element . parentNode ;
}
return element . closest ( tagName + ( className ? '.' + className : '' ) ) ;
} , [ activeFormat , value . start , value . end , tagName , className ] ) ;
2018-12-14 12:02:53 +01:00
}
2022-09-20 17:43:29 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/use-anchor.js
/ * *
* WordPress dependencies
* /
2023-06-27 16:24:19 +02:00
/** @typedef {import('../register-format-type').WPFormat} WPFormat */
/** @typedef {import('../types').RichTextValue} RichTextValue */
2019-01-29 19:23:55 +01:00
/ * *
2023-06-27 16:24:19 +02:00
* Given a range and a format tag name and class name , returns the closest
* format element .
*
* @ param { Range } range The Range to check .
* @ param { HTMLElement } editableContentElement The editable wrapper .
* @ param { string } tagName The tag name of the format element .
* @ param { string } className The class name of the format element .
*
* @ return { HTMLElement | undefined } The format element , if found .
2019-01-29 19:23:55 +01:00
* /
2023-06-27 16:24:19 +02:00
function getFormatElement ( range , editableContentElement , tagName , className ) {
let element = range . startContainer ; // If the caret is right before the element, select the next element.
2019-01-29 19:23:55 +01:00
2023-06-27 16:24:19 +02:00
element = element . nextElementSibling || element ;
2020-01-08 12:57:23 +01:00
2023-06-27 16:24:19 +02:00
if ( element . nodeType !== element . ELEMENT _NODE ) {
element = element . parentElement ;
}
if ( ! element ) return ;
if ( element === editableContentElement ) return ;
if ( ! editableContentElement . contains ( element ) ) return ;
const selector = tagName + ( className ? '.' + className : '' ) ; // .closest( selector ), but with a boundary. Check if the element matches
// the selector. If it doesn't match, try the parent element if it's not the
// editable wrapper. We don't want to try to match ancestors of the editable
// wrapper, which is what .closest( selector ) would do. When the element is
// the editable wrapper (which is most likely the case because most text is
// unformatted), this never runs.
while ( element !== editableContentElement ) {
if ( element . matches ( selector ) ) {
return element ;
}
2020-10-13 15:10:30 +02:00
2023-06-27 16:24:19 +02:00
element = element . parentElement ;
}
}
2022-09-20 17:43:29 +02:00
/ * *
* @ typedef { Object } VirtualAnchorElement
2023-06-27 16:24:19 +02:00
* @ property { ( ) => DOMRect } getBoundingClientRect A function returning a DOMRect
* @ property { Document } ownerDocument The element ' s ownerDocument
2022-09-20 17:43:29 +02:00
* /
2020-10-13 15:10:30 +02:00
2023-06-27 16:24:19 +02:00
/ * *
* Creates a virtual anchor element for a range .
*
* @ param { Range } range The range to create a virtual anchor element for .
* @ param { HTMLElement } editableContentElement The editable wrapper .
*
* @ return { VirtualAnchorElement } The virtual anchor element .
* /
function createVirtualAnchorElement ( range , editableContentElement ) {
return {
ownerDocument : range . startContainer . ownerDocument ,
getBoundingClientRect ( ) {
return editableContentElement . contains ( range . startContainer ) ? range . getBoundingClientRect ( ) : editableContentElement . getBoundingClientRect ( ) ;
}
} ;
}
/ * *
* Get the anchor : a format element if there is a matching one based on the
* tagName and className or a range otherwise .
*
* @ param { HTMLElement } editableContentElement The editable wrapper .
* @ param { string } tagName The tag name of the format
* element .
* @ param { string } className The class name of the format
* element .
*
* @ return { HTMLElement | VirtualAnchorElement | undefined } The anchor .
* /
function getAnchor ( editableContentElement , tagName , className ) {
if ( ! editableContentElement ) return ;
const {
ownerDocument
} = editableContentElement ;
const {
defaultView
} = ownerDocument ;
const selection = defaultView . getSelection ( ) ;
if ( ! selection ) return ;
if ( ! selection . rangeCount ) return ;
const range = selection . getRangeAt ( 0 ) ;
if ( ! range || ! range . startContainer ) return ;
const formatElement = getFormatElement ( range , editableContentElement , tagName , className ) ;
if ( formatElement ) return formatElement ;
return createVirtualAnchorElement ( range , editableContentElement ) ;
}
2019-01-29 19:23:55 +01:00
/ * *
2022-09-20 17:43:29 +02:00
* This hook , to be used in a format type ' s Edit component , returns the active
* element that is formatted , or a virtual element for the selection range if
* no format is active . The returned value is meant to be used for positioning
* UI , e . g . by passing it to the ` Popover ` component via the ` anchor ` prop .
2019-01-29 19:23:55 +01:00
*
2023-06-27 16:24:19 +02:00
* @ param { Object } $1 Named parameters .
* @ param { HTMLElement | null } $1 . editableContentElement The element containing
* the editable content .
* @ param { WPFormat = } $1 . settings The format type ' s settings .
2022-09-20 17:43:29 +02:00
* @ return { Element | VirtualAnchorElement | undefined | null } The active element or selection range .
2019-01-29 19:23:55 +01:00
* /
2023-06-27 16:24:19 +02:00
function useAnchor ( {
editableContentElement ,
settings = { }
} ) {
2021-05-19 17:09:27 +02:00
const {
tagName ,
2023-06-27 16:24:19 +02:00
className
2021-05-19 17:09:27 +02:00
} = settings ;
2023-06-27 16:24:19 +02:00
const [ anchor , setAnchor ] = ( 0 , external _wp _element _namespaceObject . useState ) ( ( ) => getAnchor ( editableContentElement , tagName , className ) ) ;
( 0 , external _wp _element _namespaceObject . useLayoutEffect ) ( ( ) => {
2022-09-20 17:43:29 +02:00
if ( ! editableContentElement ) return ;
2021-05-19 17:09:27 +02:00
const {
2023-06-27 16:24:19 +02:00
ownerDocument
2022-09-20 17:43:29 +02:00
} = editableContentElement ;
2021-01-28 03:04:13 +01:00
2023-06-27 16:24:19 +02:00
function callback ( ) {
setAnchor ( getAnchor ( editableContentElement , tagName , className ) ) ;
2021-01-28 03:04:13 +01:00
}
2023-06-27 16:24:19 +02:00
function attach ( ) {
ownerDocument . addEventListener ( 'selectionchange' , callback ) ;
2021-01-28 03:04:13 +01:00
}
2023-06-27 16:24:19 +02:00
function detach ( ) {
ownerDocument . removeEventListener ( 'selectionchange' , callback ) ;
}
2021-01-28 03:04:13 +01:00
2023-06-27 16:24:19 +02:00
if ( editableContentElement === ownerDocument . activeElement ) {
attach ( ) ;
2021-01-28 03:04:13 +01:00
}
2023-06-27 16:24:19 +02:00
editableContentElement . addEventListener ( 'focusin' , attach ) ;
editableContentElement . addEventListener ( 'focusout' , detach ) ;
return detach ;
} , [ editableContentElement , tagName , className ] ) ;
return anchor ;
2021-01-28 03:04:13 +01:00
}
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: external ["wp","compose"]
var external _wp _compose _namespaceObject = window [ "wp" ] [ "compose" ] ;
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/use-default-style.js
Block Editor: Update packages to bring a selection of bugfixes in.
Props iseulde, kjellr, aduth, 0mirka00, mcsf, nosolosw, gziolo, jasmussen, talldanwp, notnownikki, swissspidy, jorgefilipecosta, noisysocks.
See https://github.com/WordPress/gutenberg/pull/14796.
Fixes #46801.
Built from https://develop.svn.wordpress.org/trunk@45138
git-svn-id: http://core.svn.wordpress.org/trunk@44947 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2019-04-08 08:37:57 +02:00
/ * *
2021-05-21 12:14:23 +02:00
* WordPress dependencies
Block Editor: Update packages to bring a selection of bugfixes in.
Props iseulde, kjellr, aduth, 0mirka00, mcsf, nosolosw, gziolo, jasmussen, talldanwp, notnownikki, swissspidy, jorgefilipecosta, noisysocks.
See https://github.com/WordPress/gutenberg/pull/14796.
Fixes #46801.
Built from https://develop.svn.wordpress.org/trunk@45138
git-svn-id: http://core.svn.wordpress.org/trunk@44947 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2019-04-08 08:37:57 +02:00
* /
/ * *
2021-05-21 12:14:23 +02:00
* In HTML , leading and trailing spaces are not visible , and multiple spaces
* elsewhere are visually reduced to one space . This rule prevents spaces from
* collapsing so all space is visible in the editor and can be removed . It also
* prevents some browsers from inserting non - breaking spaces at the end of a
* line to prevent the space from visually disappearing . Sometimes these non
* breaking spaces can linger in the editor causing unwanted non breaking spaces
* in between words . If also prevent Firefox from inserting a trailing ` br ` node
* to visualise any trailing space , causing the element to be saved .
Block Editor: Update packages to bring a selection of bugfixes in.
Props iseulde, kjellr, aduth, 0mirka00, mcsf, nosolosw, gziolo, jasmussen, talldanwp, notnownikki, swissspidy, jorgefilipecosta, noisysocks.
See https://github.com/WordPress/gutenberg/pull/14796.
Fixes #46801.
Built from https://develop.svn.wordpress.org/trunk@45138
git-svn-id: http://core.svn.wordpress.org/trunk@44947 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2019-04-08 08:37:57 +02:00
*
2021-05-21 12:14:23 +02:00
* > Authors are encouraged to set the 'white-space' property on editing hosts
* > and on markup that was originally created through these editing mechanisms
* > to the value 'pre-wrap' . Default HTML whitespace handling is not well
* > suited to WYSIWYG editing , and line wrapping will not work correctly in
* > some corner cases if 'white-space' is left at its default value .
Block Editor: Update packages to bring a selection of bugfixes in.
Props iseulde, kjellr, aduth, 0mirka00, mcsf, nosolosw, gziolo, jasmussen, talldanwp, notnownikki, swissspidy, jorgefilipecosta, noisysocks.
See https://github.com/WordPress/gutenberg/pull/14796.
Fixes #46801.
Built from https://develop.svn.wordpress.org/trunk@45138
git-svn-id: http://core.svn.wordpress.org/trunk@44947 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2019-04-08 08:37:57 +02:00
*
2021-05-21 12:14:23 +02:00
* https : //html.spec.whatwg.org/multipage/interaction.html#best-practices-for-in-page-editors
2021-01-28 03:04:13 +01:00
*
2021-05-21 12:14:23 +02:00
* @ type { string }
2021-01-28 03:04:13 +01:00
* /
2021-05-21 12:14:23 +02:00
const whiteSpace = 'pre-wrap' ;
2020-01-22 23:06:21 +01:00
/ * *
2021-05-21 12:14:23 +02:00
* A minimum width of 1 px will prevent the rich text container from collapsing
* to 0 width and hiding the caret . This is useful for inline containers .
2020-01-22 23:06:21 +01:00
* /
2021-05-21 12:14:23 +02:00
const minWidth = '1px' ;
function useDefaultStyle ( ) {
2022-04-11 14:04:30 +02:00
return ( 0 , external _wp _element _namespaceObject . useCallback ) ( element => {
2021-05-21 12:14:23 +02:00
if ( ! element ) return ;
element . style . whiteSpace = whiteSpace ;
element . style . minWidth = minWidth ;
} , [ ] ) ;
2020-01-22 23:06:21 +01:00
}
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/use-boundary-style.js
2020-01-22 23:06:21 +01:00
/ * *
* WordPress dependencies
* /
2020-10-13 15:10:30 +02:00
/ *
2020-01-22 23:06:21 +01:00
* Calculates and renders the format boundary style when the active formats
* change .
* /
2023-06-27 16:24:19 +02:00
function useBoundaryStyle ( {
record
} ) {
2022-04-11 14:04:30 +02:00
const ref = ( 0 , external _wp _element _namespaceObject . useRef ) ( ) ;
2021-05-21 12:14:23 +02:00
const {
2023-06-27 16:24:19 +02:00
activeFormats = [ ] ,
replacements ,
start
2021-05-21 12:14:23 +02:00
} = record . current ;
2023-06-27 16:24:19 +02:00
const activeReplacement = replacements [ start ] ;
2022-04-11 14:04:30 +02:00
( 0 , external _wp _element _namespaceObject . useEffect ) ( ( ) => {
2020-01-22 23:06:21 +01:00
// There's no need to recalculate the boundary styles if no formats are
// active, because no boundary styles will be visible.
2023-06-27 16:24:19 +02:00
if ( ( ! activeFormats || ! activeFormats . length ) && ! activeReplacement ) {
2020-01-22 23:06:21 +01:00
return ;
}
2021-05-19 17:09:27 +02:00
const boundarySelector = '*[data-rich-text-format-boundary]' ;
const element = ref . current . querySelector ( boundarySelector ) ;
2020-01-22 23:06:21 +01:00
if ( ! element ) {
return ;
}
2021-05-19 17:09:27 +02:00
const {
ownerDocument
} = element ;
const {
defaultView
} = ownerDocument ;
const computedStyle = defaultView . getComputedStyle ( element ) ;
const newColor = computedStyle . color . replace ( ')' , ', 0.2)' ) . replace ( 'rgb' , 'rgba' ) ;
const selector = ` .rich-text:focus ${ boundarySelector } ` ;
const rule = ` background-color: ${ newColor } ` ;
const style = ` ${ selector } { ${ rule } } ` ;
const globalStyleId = 'rich-text-boundary-style' ;
let globalStyle = ownerDocument . getElementById ( globalStyleId ) ;
2020-06-26 15:33:47 +02:00
if ( ! globalStyle ) {
globalStyle = ownerDocument . createElement ( 'style' ) ;
globalStyle . id = globalStyleId ;
ownerDocument . head . appendChild ( globalStyle ) ;
}
2020-01-22 23:06:21 +01:00
if ( globalStyle . innerHTML !== style ) {
globalStyle . innerHTML = style ;
}
2023-06-27 16:24:19 +02:00
} , [ activeFormats , activeReplacement ] ) ;
2021-05-21 12:14:23 +02:00
return ref ;
2020-01-22 23:06:21 +01:00
}
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/use-copy-handler.js
2021-04-15 17:19:43 +02:00
/ * *
* WordPress dependencies
* /
2021-05-19 17:09:27 +02:00
2021-04-15 17:19:43 +02:00
/ * *
* Internal dependencies
* /
2021-05-19 17:09:27 +02:00
function useCopyHandler ( props ) {
2022-04-11 14:04:30 +02:00
const propsRef = ( 0 , external _wp _element _namespaceObject . useRef ) ( props ) ;
2021-05-19 17:09:27 +02:00
propsRef . current = props ;
2022-04-11 14:04:30 +02:00
return ( 0 , external _wp _compose _namespaceObject . useRefEffect ) ( element => {
2021-04-15 17:19:43 +02:00
function onCopy ( event ) {
2021-05-19 17:09:27 +02:00
const {
record ,
multilineTag ,
preserveWhiteSpace
} = propsRef . current ;
2023-06-27 16:24:19 +02:00
const {
ownerDocument
} = element ;
2021-05-19 17:09:27 +02:00
2023-06-27 16:24:19 +02:00
if ( isCollapsed ( record . current ) || ! element . contains ( ownerDocument . activeElement ) ) {
2021-04-15 17:19:43 +02:00
return ;
}
2021-05-19 17:09:27 +02:00
const selectedRecord = slice ( record . current ) ;
const plainText = getTextContent ( selectedRecord ) ;
const html = toHTMLString ( {
2021-04-15 17:19:43 +02:00
value : selectedRecord ,
2021-05-19 17:09:27 +02:00
multilineTag ,
preserveWhiteSpace
2021-04-15 17:19:43 +02:00
} ) ;
event . clipboardData . setData ( 'text/plain' , plainText ) ;
event . clipboardData . setData ( 'text/html' , html ) ;
event . clipboardData . setData ( 'rich-text' , 'true' ) ;
2021-11-08 15:29:21 +01:00
event . clipboardData . setData ( 'rich-text-multi-line-tag' , multilineTag || '' ) ;
2021-04-15 17:19:43 +02:00
event . preventDefault ( ) ;
2023-06-27 16:24:19 +02:00
if ( event . type === 'cut' ) {
ownerDocument . execCommand ( 'delete' ) ;
}
2021-04-15 17:19:43 +02:00
}
element . addEventListener ( 'copy' , onCopy ) ;
2023-06-27 16:24:19 +02:00
element . addEventListener ( 'cut' , onCopy ) ;
2021-05-19 17:09:27 +02:00
return ( ) => {
2021-04-15 17:19:43 +02:00
element . removeEventListener ( 'copy' , onCopy ) ;
2023-06-27 16:24:19 +02:00
element . removeEventListener ( 'cut' , onCopy ) ;
2021-04-15 17:19:43 +02:00
} ;
2021-05-19 17:09:27 +02:00
} , [ ] ) ;
2021-04-15 17:19:43 +02:00
}
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: external ["wp","keycodes"]
var external _wp _keycodes _namespaceObject = window [ "wp" ] [ "keycodes" ] ;
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/use-format-boundaries.js
2021-05-19 17:09:27 +02:00
/ * *
* WordPress dependencies
* /
/ * *
* Internal dependencies
* /
const EMPTY _ACTIVE _FORMATS = [ ] ;
function useFormatBoundaries ( props ) {
2022-04-11 14:04:30 +02:00
const [ , forceRender ] = ( 0 , external _wp _element _namespaceObject . useReducer ) ( ( ) => ( { } ) ) ;
const propsRef = ( 0 , external _wp _element _namespaceObject . useRef ) ( props ) ;
2021-05-19 17:09:27 +02:00
propsRef . current = props ;
2022-04-11 14:04:30 +02:00
return ( 0 , external _wp _compose _namespaceObject . useRefEffect ) ( element => {
2021-05-19 17:09:27 +02:00
function onKeyDown ( event ) {
const {
keyCode ,
shiftKey ,
altKey ,
metaKey ,
ctrlKey
} = event ;
if ( // Only override left and right keys without modifiers pressed.
2022-04-11 14:04:30 +02:00
shiftKey || altKey || metaKey || ctrlKey || keyCode !== external _wp _keycodes _namespaceObject . LEFT && keyCode !== external _wp _keycodes _namespaceObject . RIGHT ) {
2021-05-19 17:09:27 +02:00
return ;
}
const {
record ,
2021-05-21 12:14:23 +02:00
applyRecord
2021-05-19 17:09:27 +02:00
} = propsRef . current ;
const {
text ,
formats ,
start ,
end ,
activeFormats : currentActiveFormats = [ ]
} = record . current ;
const collapsed = isCollapsed ( record . current ) ;
const {
ownerDocument
} = element ;
const {
defaultView
} = ownerDocument ; // To do: ideally, we should look at visual position instead.
const {
direction
} = defaultView . getComputedStyle ( element ) ;
2022-04-11 14:04:30 +02:00
const reverseKey = direction === 'rtl' ? external _wp _keycodes _namespaceObject . RIGHT : external _wp _keycodes _namespaceObject . LEFT ;
2021-05-19 17:09:27 +02:00
const isReverse = event . keyCode === reverseKey ; // If the selection is collapsed and at the very start, do nothing if
// navigating backward.
// If the selection is collapsed and at the very end, do nothing if
// navigating forward.
if ( collapsed && currentActiveFormats . length === 0 ) {
if ( start === 0 && isReverse ) {
return ;
}
2018-12-14 12:02:53 +01:00
2021-05-19 17:09:27 +02:00
if ( end === text . length && ! isReverse ) {
return ;
}
} // If the selection is not collapsed, let the browser handle collapsing
// the selection for now. Later we could expand this logic to set
// boundary positions if needed.
2018-12-14 12:02:53 +01:00
2021-05-19 17:09:27 +02:00
if ( ! collapsed ) {
return ;
}
2018-12-14 12:02:53 +01:00
2021-05-19 17:09:27 +02:00
const formatsBefore = formats [ start - 1 ] || EMPTY _ACTIVE _FORMATS ;
const formatsAfter = formats [ start ] || EMPTY _ACTIVE _FORMATS ;
2021-11-08 15:29:21 +01:00
const destination = isReverse ? formatsBefore : formatsAfter ;
const isIncreasing = currentActiveFormats . every ( ( format , index ) => format === destination [ index ] ) ;
2021-05-19 17:09:27 +02:00
let newActiveFormatsLength = currentActiveFormats . length ;
2021-01-28 03:04:13 +01:00
2021-11-08 15:29:21 +01:00
if ( ! isIncreasing ) {
newActiveFormatsLength -- ;
} else if ( newActiveFormatsLength < destination . length ) {
newActiveFormatsLength ++ ;
2021-05-19 17:09:27 +02:00
}
if ( newActiveFormatsLength === currentActiveFormats . length ) {
2021-11-08 15:29:21 +01:00
record . current . _newActiveFormats = destination ;
2021-05-19 17:09:27 +02:00
return ;
}
event . preventDefault ( ) ;
2021-11-08 15:29:21 +01:00
const origin = isReverse ? formatsAfter : formatsBefore ;
const source = isIncreasing ? destination : origin ;
2021-05-19 17:09:27 +02:00
const newActiveFormats = source . slice ( 0 , newActiveFormatsLength ) ;
const newValue = { ... record . current ,
activeFormats : newActiveFormats
} ;
record . current = newValue ;
applyRecord ( newValue ) ;
2021-05-21 12:14:23 +02:00
forceRender ( ) ;
2021-05-19 17:09:27 +02:00
}
element . addEventListener ( 'keydown' , onKeyDown ) ;
return ( ) => {
element . removeEventListener ( 'keydown' , onKeyDown ) ;
} ;
} , [ ] ) ;
}
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/use-select-object.js
2021-05-19 17:09:27 +02:00
/ * *
* WordPress dependencies
* /
2021-05-21 12:14:23 +02:00
function useSelectObject ( ) {
2022-04-11 14:04:30 +02:00
return ( 0 , external _wp _compose _namespaceObject . useRefEffect ) ( element => {
2021-05-21 12:14:23 +02:00
function onClick ( event ) {
2021-05-19 17:09:27 +02:00
const {
2021-05-21 12:14:23 +02:00
target
} = event ; // If the child element has no text content, it must be an object.
2021-05-19 17:09:27 +02:00
2023-06-27 16:24:19 +02:00
if ( target === element || target . textContent && target . isContentEditable ) {
2021-05-19 17:09:27 +02:00
return ;
}
2021-05-21 12:14:23 +02:00
const {
ownerDocument
} = target ;
const {
defaultView
} = ownerDocument ;
2023-06-27 16:24:19 +02:00
const selection = defaultView . getSelection ( ) ; // If it's already selected, do nothing and let default behavior
// happen. This means it's "click-through".
if ( selection . containsNode ( target ) ) return ;
2023-07-11 08:59:09 +02:00
const range = ownerDocument . createRange ( ) ; // If the target is within a non editable element, select the non
// editable element.
const nodeToSelect = target . isContentEditable ? target : target . closest ( '[contenteditable]' ) ;
range . selectNode ( nodeToSelect ) ;
2021-05-21 12:14:23 +02:00
selection . removeAllRanges ( ) ;
selection . addRange ( range ) ;
2023-06-27 16:24:19 +02:00
event . preventDefault ( ) ;
}
function onFocusIn ( event ) {
// When there is incoming focus from a link, select the object.
if ( event . relatedTarget && ! element . contains ( event . relatedTarget ) && event . relatedTarget . tagName === 'A' ) {
onClick ( event ) ;
}
2021-05-19 17:09:27 +02:00
}
2021-05-21 12:14:23 +02:00
element . addEventListener ( 'click' , onClick ) ;
2023-06-27 16:24:19 +02:00
element . addEventListener ( 'focusin' , onFocusIn ) ;
2021-05-19 17:09:27 +02:00
return ( ) => {
2021-05-21 12:14:23 +02:00
element . removeEventListener ( 'click' , onClick ) ;
2023-06-27 16:24:19 +02:00
element . removeEventListener ( 'focusin' , onFocusIn ) ;
2021-05-19 17:09:27 +02:00
} ;
} , [ ] ) ;
}
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/update-formats.js
2021-05-21 12:14:23 +02:00
/ * *
* Internal dependencies
* /
2018-12-14 12:02:53 +01:00
2023-06-27 16:24:19 +02:00
/** @typedef {import('./types').RichTextValue} RichTextValue */
2020-01-08 12:57:23 +01:00
2019-09-19 17:19:18 +02:00
/ * *
2021-05-21 12:14:23 +02:00
* Efficiently updates all the formats from ` start ` ( including ) until ` end `
* ( excluding ) with the active formats . Mutates ` value ` .
2019-09-19 17:19:18 +02:00
*
2021-11-08 15:29:21 +01:00
* @ param { Object } $1 Named paramentes .
* @ param { RichTextValue } $1 . value Value te update .
* @ param { number } $1 . start Index to update from .
* @ param { number } $1 . end Index to update until .
* @ param { Array } $1 . formats Replacement formats .
2019-09-19 17:19:18 +02:00
*
2021-05-21 12:14:23 +02:00
* @ return { RichTextValue } Mutated value .
2019-09-19 17:19:18 +02:00
* /
2018-12-18 04:14:52 +01:00
2023-06-27 16:24:19 +02:00
function updateFormats ( {
value ,
start ,
end ,
formats
} ) {
2021-11-08 15:29:21 +01:00
// Start and end may be switched in case of delete.
const min = Math . min ( start , end ) ;
const max = Math . max ( start , end ) ;
const formatsBefore = value . formats [ min - 1 ] || [ ] ;
const formatsAfter = value . formats [ max ] || [ ] ; // First, fix the references. If any format right before or after are
2021-05-21 12:14:23 +02:00
// equal, the replacement format should use the same reference.
value . activeFormats = formats . map ( ( format , index ) => {
if ( formatsBefore [ index ] ) {
if ( isFormatEqual ( format , formatsBefore [ index ] ) ) {
return formatsBefore [ index ] ;
}
} else if ( formatsAfter [ index ] ) {
if ( isFormatEqual ( format , formatsAfter [ index ] ) ) {
return formatsAfter [ index ] ;
}
}
return format ;
} ) ;
while ( -- end >= start ) {
if ( value . activeFormats . length > 0 ) {
value . formats [ end ] = value . activeFormats ;
} else {
delete value . formats [ end ] ;
}
}
return value ;
}
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/use-input-and-selection.js
2020-01-08 12:57:23 +01:00
/ * *
2021-05-21 12:14:23 +02:00
* WordPress dependencies
2020-01-08 12:57:23 +01:00
* /
2021-05-21 12:14:23 +02:00
2021-04-15 17:19:43 +02:00
/ * *
2021-05-21 12:14:23 +02:00
* Internal dependencies
2021-04-15 17:19:43 +02:00
* /
2021-05-21 12:14:23 +02:00
2020-01-08 12:57:23 +01:00
/ * *
2021-05-21 12:14:23 +02:00
* All inserting input types that would insert HTML into the DOM .
*
* @ see https : //www.w3.org/TR/input-events-2/#interface-InputEvent-Attributes
2020-01-08 12:57:23 +01:00
*
2021-05-21 12:14:23 +02:00
* @ type { Set }
2020-01-08 12:57:23 +01:00
* /
2021-05-21 12:14:23 +02:00
const INSERTION _INPUT _TYPES _TO _IGNORE = new Set ( [ 'insertParagraph' , 'insertOrderedList' , 'insertUnorderedList' , 'insertHorizontalRule' , 'insertLink' ] ) ;
const use _input _and _selection _EMPTY _ACTIVE _FORMATS = [ ] ;
2022-09-20 17:43:29 +02:00
const PLACEHOLDER _ATTR _NAME = 'data-rich-text-placeholder' ;
2019-10-15 18:17:12 +02:00
/ * *
* If the selection is set on the placeholder element , collapse the selection to
* the start ( before the placeholder ) .
2020-06-26 15:33:47 +02:00
*
* @ param { Window } defaultView
2019-10-15 18:17:12 +02:00
* /
2020-06-26 15:33:47 +02:00
function fixPlaceholderSelection ( defaultView ) {
2021-05-19 17:09:27 +02:00
const selection = defaultView . getSelection ( ) ;
const {
anchorNode ,
anchorOffset
} = selection ;
2019-10-15 18:17:12 +02:00
if ( anchorNode . nodeType !== anchorNode . ELEMENT _NODE ) {
return ;
}
2021-05-19 17:09:27 +02:00
const targetNode = anchorNode . childNodes [ anchorOffset ] ;
2019-10-15 18:17:12 +02:00
2022-09-20 17:43:29 +02:00
if ( ! targetNode || targetNode . nodeType !== targetNode . ELEMENT _NODE || ! targetNode . hasAttribute ( PLACEHOLDER _ATTR _NAME ) ) {
2019-10-15 18:17:12 +02:00
return ;
}
selection . collapseToStart ( ) ;
}
Block Editor: Update WordPress packages to include the latest bug fixes.
Updated packages:
@wordpress/annotations@1.7.1
@wordpress/api-fetch@3.6.1
@wordpress/babel-plugin-makepot@3.2.1
@wordpress/babel-preset-default@4.6.1
@wordpress/block-directory@1.0.1
@wordpress/block-editor@3.2.1
@wordpress/block-library@2.9.1
@wordpress/blocks@6.7.1
@wordpress/components@8.3.1
@wordpress/compose@3.7.1
@wordpress/core-data@2.7.1
@wordpress/data-controls@1.3.1
@wordpress/data@4.9.1
@wordpress/docgen@1.4.1
@wordpress/dom@2.5.1
@wordpress/e2e-test-utils@2.4.1
@wordpress/e2e-tests@1.7.1
@wordpress/edit-post@3.8.1
@wordpress/editor@9.7.1
@wordpress/element@2.8.1
@wordpress/format-library@1.9.1
@wordpress/i18n@3.6.1
@wordpress/jest-console@3.3.1
@wordpress/jest-preset-default@5.1.1
@wordpress/keycodes@2.6.1
@wordpress/library-export-default-webpack-plugin@1.4.1
@wordpress/list-reusable-blocks@1.8.1
@wordpress/media-utils@1.2.1
@wordpress/notices@1.8.1
@wordpress/nux@3.7.1
@wordpress/plugins@2.7.1
@wordpress/redux-routine@3.6.1
@wordpress/rich-text@3.7.1
@wordpress/scripts@5.0.1
@wordpress/server-side-render@1.3.1
@wordpress/shortcode@2.4.1
@wordpress/token-list@1.6.1
@wordpress/viewport@2.8.1
@wordpress/wordcount@2.6.1
Props epiqueras, youknowriad, donmhico, jorgefilipecosta, soean, mcsf, noisysocks, andraganescu, gziolo, talldanwp, iseulde, nrqsnchz, mapk, karmatosed, joen, afercia, kjellr, desrosj.
Fixes #48186.
Built from https://develop.svn.wordpress.org/trunk@46364
git-svn-id: http://core.svn.wordpress.org/trunk@46163 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2019-09-30 22:07:06 +02:00
2021-05-21 12:14:23 +02:00
function useInputAndSelection ( props ) {
2022-04-11 14:04:30 +02:00
const propsRef = ( 0 , external _wp _element _namespaceObject . useRef ) ( props ) ;
2021-05-21 12:14:23 +02:00
propsRef . current = props ;
2022-04-11 14:04:30 +02:00
return ( 0 , external _wp _compose _namespaceObject . useRefEffect ) ( element => {
2021-05-21 12:14:23 +02:00
const {
ownerDocument
} = element ;
const {
defaultView
} = ownerDocument ;
let isComposing = false ;
function onInput ( event ) {
// Do not trigger a change if characters are being composed.
// Browsers will usually emit a final `input` event when the
// characters are composed.
// As of December 2019, Safari doesn't support
// nativeEvent.isComposing.
if ( isComposing ) {
return ;
}
2020-06-26 15:33:47 +02:00
2021-05-21 12:14:23 +02:00
let inputType ;
2020-06-26 15:33:47 +02:00
2021-05-21 12:14:23 +02:00
if ( event ) {
inputType = event . inputType ;
2020-06-26 15:33:47 +02:00
}
2021-05-21 12:14:23 +02:00
const {
record ,
applyRecord ,
createRecord ,
handleChange
} = propsRef . current ; // The browser formatted something or tried to insert HTML.
// Overwrite it. It will be handled later by the format library if
// needed.
if ( inputType && ( inputType . indexOf ( 'format' ) === 0 || INSERTION _INPUT _TYPES _TO _IGNORE . has ( inputType ) ) ) {
applyRecord ( record . current ) ;
return ;
}
2020-06-26 15:33:47 +02:00
2021-05-21 12:14:23 +02:00
const currentValue = createRecord ( ) ;
const {
start ,
activeFormats : oldActiveFormats = [ ]
} = record . current ; // Update the formats between the last and new caret position.
2020-06-26 15:33:47 +02:00
2021-05-21 12:14:23 +02:00
const change = updateFormats ( {
value : currentValue ,
start ,
end : currentValue . start ,
formats : oldActiveFormats
} ) ;
handleChange ( change ) ;
2019-09-19 17:19:18 +02:00
}
2021-05-21 12:14:23 +02:00
/ * *
2023-06-27 16:24:19 +02:00
* Syncs the selection to local state . A callback for the
* ` selectionchange ` event .
2021-05-21 12:14:23 +02:00
* /
2020-06-26 15:33:47 +02:00
2019-09-19 17:19:18 +02:00
2023-06-27 16:24:19 +02:00
function handleSelectionChange ( ) {
2021-05-21 12:14:23 +02:00
const {
record ,
applyRecord ,
createRecord ,
onSelectionChange
2022-05-02 12:39:04 +02:00
} = propsRef . current ; // Check if the implementor disabled editing. `contentEditable`
// does disable input, but not text selection, so we must ignore
// selection changes.
if ( element . contentEditable !== 'true' ) {
return ;
} // If the selection changes where the active element is a parent of
2022-04-12 17:12:47 +02:00
// the rich text instance (writing flow), call `onSelectionChange`
// for the rich text instance that contains the start or end of the
// selection.
2018-12-18 04:14:52 +01:00
2022-05-02 12:39:04 +02:00
2022-04-12 17:12:47 +02:00
if ( ownerDocument . activeElement !== element ) {
2022-09-20 17:43:29 +02:00
// Only process if the active elment is contentEditable, either
// this rich text instance or the writing flow parent. Fixes a
// bug in Firefox where it strangely selects the closest
// contentEditable element, even though the click was outside
// any contentEditable element.
if ( ownerDocument . activeElement . contentEditable !== 'true' ) {
return ;
}
2022-04-12 17:12:47 +02:00
if ( ! ownerDocument . activeElement . contains ( element ) ) {
return ;
}
2018-12-18 04:14:52 +01:00
2022-04-12 17:12:47 +02:00
const selection = defaultView . getSelection ( ) ;
const {
anchorNode ,
focusNode
} = selection ;
if ( element . contains ( anchorNode ) && element !== anchorNode && element . contains ( focusNode ) && element !== focusNode ) {
const {
start ,
end
} = createRecord ( ) ;
record . current . activeFormats = use _input _and _selection _EMPTY _ACTIVE _FORMATS ;
onSelectionChange ( start , end ) ;
} else if ( element . contains ( anchorNode ) && element !== anchorNode ) {
const {
start ,
end : offset = start
} = createRecord ( ) ;
record . current . activeFormats = use _input _and _selection _EMPTY _ACTIVE _FORMATS ;
onSelectionChange ( offset ) ;
2022-09-20 17:43:29 +02:00
} else if ( element . contains ( focusNode ) ) {
2022-04-12 17:12:47 +02:00
const {
start ,
end : offset = start
} = createRecord ( ) ;
record . current . activeFormats = use _input _and _selection _EMPTY _ACTIVE _FORMATS ;
onSelectionChange ( undefined , offset ) ;
}
2018-12-18 04:14:52 +01:00
2021-05-21 12:14:23 +02:00
return ;
} // In case of a keyboard event, ignore selection changes during
// composition.
2018-12-18 04:14:52 +01:00
2020-06-26 15:33:47 +02:00
2021-05-21 12:14:23 +02:00
if ( isComposing ) {
2019-09-19 17:19:18 +02:00
return ;
}
2018-12-18 04:14:52 +01:00
2021-05-21 12:14:23 +02:00
const {
start ,
end ,
text
} = createRecord ( ) ;
const oldRecord = record . current ; // Fallback mechanism for IE11, which doesn't support the input event.
// Any input results in a selection change.
2020-01-08 12:57:23 +01:00
2021-05-21 12:14:23 +02:00
if ( text !== oldRecord . text ) {
onInput ( ) ;
return ;
}
2020-01-08 12:57:23 +01:00
2021-05-21 12:14:23 +02:00
if ( start === oldRecord . start && end === oldRecord . end ) {
// Sometimes the browser may set the selection on the placeholder
// element, in which case the caret is not visible. We need to set
// the caret before the placeholder if that's the case.
if ( oldRecord . text . length === 0 && start === 0 ) {
fixPlaceholderSelection ( defaultView ) ;
}
2020-01-08 12:57:23 +01:00
2021-05-21 12:14:23 +02:00
return ;
2019-09-19 17:19:18 +02:00
}
2020-06-26 15:33:47 +02:00
2021-05-21 12:14:23 +02:00
const newValue = { ... oldRecord ,
start ,
end ,
// _newActiveFormats may be set on arrow key navigation to control
// the right boundary position. If undefined, getActiveFormats will
// give the active formats according to the browser.
activeFormats : oldRecord . _newActiveFormats ,
_newActiveFormats : undefined
} ;
const newActiveFormats = getActiveFormats ( newValue , use _input _and _selection _EMPTY _ACTIVE _FORMATS ) ; // Update the value with the new active formats.
2020-06-26 15:33:47 +02:00
2021-05-21 12:14:23 +02:00
newValue . activeFormats = newActiveFormats ; // It is important that the internal value is updated first,
// otherwise the value will be wrong on render!
2020-01-22 23:06:21 +01:00
2021-05-21 12:14:23 +02:00
record . current = newValue ;
applyRecord ( newValue , {
domOnly : true
2020-06-26 15:33:47 +02:00
} ) ;
2021-05-21 12:14:23 +02:00
onSelectionChange ( start , end ) ;
2019-09-19 17:19:18 +02:00
}
2020-06-26 15:33:47 +02:00
2021-05-21 12:14:23 +02:00
function onCompositionStart ( ) {
isComposing = true ; // Do not update the selection when characters are being composed as
2022-05-02 12:39:04 +02:00
// this rerenders the component and might destroy internal browser
2021-05-21 12:14:23 +02:00
// editing state.
2020-06-26 15:33:47 +02:00
2022-09-20 17:43:29 +02:00
ownerDocument . removeEventListener ( 'selectionchange' , handleSelectionChange ) ; // Remove the placeholder. Since the rich text value doesn't update
// during composition, the placeholder doesn't get removed. There's
// no need to re-add it, when the value is updated on compositionend
// it will be re-added when the value is empty.
2023-06-27 16:24:19 +02:00
element . querySelector ( ` [ ${ PLACEHOLDER _ATTR _NAME } ] ` ) ? . remove ( ) ;
2020-06-26 15:33:47 +02:00
}
2018-12-18 04:14:52 +01:00
2021-05-21 12:14:23 +02:00
function onCompositionEnd ( ) {
isComposing = false ; // Ensure the value is up-to-date for browsers that don't emit a final
// input event after composition.
Block Editor: Update WordPress packages to include the latest bug fixes.
Updated packages:
@wordpress/annotations@1.7.1
@wordpress/api-fetch@3.6.1
@wordpress/babel-plugin-makepot@3.2.1
@wordpress/babel-preset-default@4.6.1
@wordpress/block-directory@1.0.1
@wordpress/block-editor@3.2.1
@wordpress/block-library@2.9.1
@wordpress/blocks@6.7.1
@wordpress/components@8.3.1
@wordpress/compose@3.7.1
@wordpress/core-data@2.7.1
@wordpress/data-controls@1.3.1
@wordpress/data@4.9.1
@wordpress/docgen@1.4.1
@wordpress/dom@2.5.1
@wordpress/e2e-test-utils@2.4.1
@wordpress/e2e-tests@1.7.1
@wordpress/edit-post@3.8.1
@wordpress/editor@9.7.1
@wordpress/element@2.8.1
@wordpress/format-library@1.9.1
@wordpress/i18n@3.6.1
@wordpress/jest-console@3.3.1
@wordpress/jest-preset-default@5.1.1
@wordpress/keycodes@2.6.1
@wordpress/library-export-default-webpack-plugin@1.4.1
@wordpress/list-reusable-blocks@1.8.1
@wordpress/media-utils@1.2.1
@wordpress/notices@1.8.1
@wordpress/nux@3.7.1
@wordpress/plugins@2.7.1
@wordpress/redux-routine@3.6.1
@wordpress/rich-text@3.7.1
@wordpress/scripts@5.0.1
@wordpress/server-side-render@1.3.1
@wordpress/shortcode@2.4.1
@wordpress/token-list@1.6.1
@wordpress/viewport@2.8.1
@wordpress/wordcount@2.6.1
Props epiqueras, youknowriad, donmhico, jorgefilipecosta, soean, mcsf, noisysocks, andraganescu, gziolo, talldanwp, iseulde, nrqsnchz, mapk, karmatosed, joen, afercia, kjellr, desrosj.
Fixes #48186.
Built from https://develop.svn.wordpress.org/trunk@46364
git-svn-id: http://core.svn.wordpress.org/trunk@46163 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2019-09-30 22:07:06 +02:00
2021-05-21 12:14:23 +02:00
onInput ( {
inputType : 'insertText'
} ) ; // Tracking selection changes can be resumed.
2019-09-19 17:19:18 +02:00
2021-05-21 12:14:23 +02:00
ownerDocument . addEventListener ( 'selectionchange' , handleSelectionChange ) ;
2020-06-26 15:33:47 +02:00
}
2019-09-19 17:19:18 +02:00
2021-05-21 12:14:23 +02:00
function onFocus ( ) {
const {
record ,
isSelected ,
2021-11-08 15:29:21 +01:00
onSelectionChange ,
applyRecord
2022-04-12 17:12:47 +02:00
} = propsRef . current ; // When the whole editor is editable, let writing flow handle
// selection.
if ( element . parentElement . closest ( '[contenteditable="true"]' ) ) {
return ;
}
2020-06-26 15:33:47 +02:00
2021-05-21 12:14:23 +02:00
if ( ! isSelected ) {
// We know for certain that on focus, the old selection is invalid.
// It will be recalculated on the next mouseup, keyup, or touchend
// event.
const index = undefined ;
record . current = { ... record . current ,
start : index ,
end : index ,
activeFormats : use _input _and _selection _EMPTY _ACTIVE _FORMATS
} ;
2020-06-26 15:33:47 +02:00
} else {
2021-11-08 15:29:21 +01:00
applyRecord ( record . current ) ;
2021-05-21 12:14:23 +02:00
onSelectionChange ( record . current . start , record . current . end ) ;
2023-06-27 16:24:19 +02:00
}
2020-06-26 15:33:47 +02:00
}
2019-09-19 17:19:18 +02:00
2021-05-21 12:14:23 +02:00
element . addEventListener ( 'input' , onInput ) ;
element . addEventListener ( 'compositionstart' , onCompositionStart ) ;
element . addEventListener ( 'compositionend' , onCompositionEnd ) ;
2023-06-27 16:24:19 +02:00
element . addEventListener ( 'focus' , onFocus ) ;
2022-04-12 17:12:47 +02:00
ownerDocument . addEventListener ( 'selectionchange' , handleSelectionChange ) ;
2021-05-21 12:14:23 +02:00
return ( ) => {
element . removeEventListener ( 'input' , onInput ) ;
element . removeEventListener ( 'compositionstart' , onCompositionStart ) ;
element . removeEventListener ( 'compositionend' , onCompositionEnd ) ;
element . removeEventListener ( 'focus' , onFocus ) ;
ownerDocument . removeEventListener ( 'selectionchange' , handleSelectionChange ) ;
2023-06-27 16:24:19 +02:00
} ;
} , [ ] ) ;
}
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/use-selection-change-compat.js
/ * *
* WordPress dependencies
* /
/ * *
* Internal dependencies
* /
/ * *
* Sometimes some browsers are not firing a ` selectionchange ` event when
* changing the selection by mouse or keyboard . This hook makes sure that , if we
* detect no ` selectionchange ` or ` input ` event between the up and down events ,
* we fire a ` selectionchange ` event .
*
* @ return { import ( '@wordpress/compose' ) . RefEffect } A ref effect attaching the
* listeners .
* /
function useSelectionChangeCompat ( ) {
return ( 0 , external _wp _compose _namespaceObject . useRefEffect ) ( element => {
const {
ownerDocument
} = element ;
const {
defaultView
} = ownerDocument ;
2023-07-28 09:40:16 +02:00
const selection = defaultView ? . getSelection ( ) ;
2023-06-27 16:24:19 +02:00
let range ;
function getRange ( ) {
return selection . rangeCount ? selection . getRangeAt ( 0 ) : null ;
}
function onDown ( event ) {
const type = event . type === 'keydown' ? 'keyup' : 'pointerup' ;
function onCancel ( ) {
ownerDocument . removeEventListener ( type , onUp ) ;
ownerDocument . removeEventListener ( 'selectionchange' , onCancel ) ;
ownerDocument . removeEventListener ( 'input' , onCancel ) ;
}
function onUp ( ) {
onCancel ( ) ;
if ( isRangeEqual ( range , getRange ( ) ) ) return ;
ownerDocument . dispatchEvent ( new Event ( 'selectionchange' ) ) ;
}
ownerDocument . addEventListener ( type , onUp ) ;
ownerDocument . addEventListener ( 'selectionchange' , onCancel ) ;
ownerDocument . addEventListener ( 'input' , onCancel ) ;
range = getRange ( ) ;
}
element . addEventListener ( 'pointerdown' , onDown ) ;
element . addEventListener ( 'keydown' , onDown ) ;
return ( ) => {
element . removeEventListener ( 'pointerdown' , onDown ) ;
element . removeEventListener ( 'keydown' , onDown ) ;
2021-05-21 12:14:23 +02:00
} ;
} , [ ] ) ;
}
2019-09-19 17:19:18 +02:00
2022-09-20 17:43:29 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/remove-line-separator.js
/ * *
* Internal dependencies
* /
2023-06-27 16:24:19 +02:00
/** @typedef {import('./types').RichTextValue} RichTextValue */
2022-09-20 17:43:29 +02:00
/ * *
* Removes a line separator character , if existing , from a Rich Text value at
* the current indices . If no line separator exists on the indices it will
* return undefined .
*
* @ param { RichTextValue } value Value to modify .
* @ param { boolean } backward Indicates if are removing from the start
* index or the end index .
*
* @ return { RichTextValue | undefined } A new value with the line separator
* removed . Or undefined if no line separator
* is found on the position .
* /
2023-06-27 16:24:19 +02:00
function removeLineSeparator ( value , backward = true ) {
2022-09-20 17:43:29 +02:00
const {
replacements ,
text ,
start ,
end
} = value ;
const collapsed = isCollapsed ( value ) ;
let index = start - 1 ;
let removeStart = collapsed ? start - 1 : start ;
let removeEnd = end ;
if ( ! backward ) {
index = end ;
removeStart = start ;
removeEnd = collapsed ? end + 1 : end ;
}
if ( text [ index ] !== LINE _SEPARATOR ) {
return ;
}
let newValue ; // If the line separator that is about te be removed
// contains wrappers, remove the wrappers first.
if ( collapsed && replacements [ index ] && replacements [ index ] . length ) {
const newReplacements = replacements . slice ( ) ;
newReplacements [ index ] = replacements [ index ] . slice ( 0 , - 1 ) ;
newValue = { ... value ,
replacements : newReplacements
} ;
} else {
newValue = remove ( value , removeStart , removeEnd ) ;
}
return newValue ;
}
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/use-delete.js
2021-05-21 12:14:23 +02:00
/ * *
* WordPress dependencies
* /
2020-01-22 23:06:21 +01:00
2019-09-19 17:19:18 +02:00
2020-01-08 12:57:23 +01:00
2021-05-21 12:14:23 +02:00
/ * *
* Internal dependencies
* /
2020-06-26 15:33:47 +02:00
2019-09-19 17:19:18 +02:00
2021-05-21 12:14:23 +02:00
function useDelete ( props ) {
2022-04-11 14:04:30 +02:00
const propsRef = ( 0 , external _wp _element _namespaceObject . useRef ) ( props ) ;
2021-05-21 12:14:23 +02:00
propsRef . current = props ;
2022-04-11 14:04:30 +02:00
return ( 0 , external _wp _compose _namespaceObject . useRefEffect ) ( element => {
2021-05-21 12:14:23 +02:00
function onKeyDown ( event ) {
const {
keyCode
} = event ;
const {
createRecord ,
handleChange ,
multilineTag
} = propsRef . current ;
2019-09-19 17:19:18 +02:00
2021-05-21 12:14:23 +02:00
if ( event . defaultPrevented ) {
return ;
}
2019-09-19 17:19:18 +02:00
2022-04-11 14:04:30 +02:00
if ( keyCode !== external _wp _keycodes _namespaceObject . DELETE && keyCode !== external _wp _keycodes _namespaceObject . BACKSPACE ) {
2021-05-21 12:14:23 +02:00
return ;
}
2019-09-19 17:19:18 +02:00
2021-05-21 12:14:23 +02:00
const currentValue = createRecord ( ) ;
const {
start ,
end ,
text
} = currentValue ;
2022-04-11 14:04:30 +02:00
const isReverse = keyCode === external _wp _keycodes _namespaceObject . BACKSPACE ; // Always handle full content deletion ourselves.
2020-01-08 12:57:23 +01:00
2021-05-21 12:14:23 +02:00
if ( start === 0 && end !== 0 && end === text . length ) {
2022-04-11 14:04:30 +02:00
handleChange ( remove ( currentValue ) ) ;
2021-05-21 12:14:23 +02:00
event . preventDefault ( ) ;
return ;
}
2019-09-19 17:19:18 +02:00
2021-05-21 12:14:23 +02:00
if ( multilineTag ) {
let newValue ; // Check to see if we should remove the first item if empty.
2019-09-19 17:19:18 +02:00
2021-05-21 12:14:23 +02:00
if ( isReverse && currentValue . start === 0 && currentValue . end === 0 && isEmptyLine ( currentValue ) ) {
newValue = removeLineSeparator ( currentValue , ! isReverse ) ;
} else {
newValue = removeLineSeparator ( currentValue , isReverse ) ;
}
2020-06-26 15:33:47 +02:00
2021-05-21 12:14:23 +02:00
if ( newValue ) {
handleChange ( newValue ) ;
event . preventDefault ( ) ;
}
}
2020-06-26 15:33:47 +02:00
}
2019-09-19 17:19:18 +02:00
2021-05-21 12:14:23 +02:00
element . addEventListener ( 'keydown' , onKeyDown ) ;
return ( ) => {
element . removeEventListener ( 'keydown' , onKeyDown ) ;
} ;
} , [ ] ) ;
}
2019-09-19 17:19:18 +02:00
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/index.js
2021-05-21 12:14:23 +02:00
/ * *
* WordPress dependencies
* /
2019-09-19 17:19:18 +02:00
2021-11-08 15:29:21 +01:00
2021-05-21 12:14:23 +02:00
/ * *
* Internal dependencies
* /
2019-09-19 17:19:18 +02:00
2020-06-26 15:33:47 +02:00
2019-09-19 17:19:18 +02:00
2020-06-26 15:33:47 +02:00
2019-09-19 17:19:18 +02:00
2020-06-26 15:33:47 +02:00
2019-09-19 17:19:18 +02:00
2023-06-27 16:24:19 +02:00
function useRichText ( {
value = '' ,
selectionStart ,
selectionEnd ,
placeholder ,
preserveWhiteSpace ,
onSelectionChange ,
onChange ,
_ _unstableMultilineTag : multilineTag ,
_ _unstableDisableFormats : disableFormats ,
_ _unstableIsSelected : isSelected ,
_ _unstableDependencies = [ ] ,
_ _unstableAfterParse ,
_ _unstableBeforeSerialize ,
_ _unstableAddInvisibleFormats
} ) {
2022-04-11 14:04:30 +02:00
const registry = ( 0 , external _wp _data _namespaceObject . useRegistry ) ( ) ;
const [ , forceRender ] = ( 0 , external _wp _element _namespaceObject . useReducer ) ( ( ) => ( { } ) ) ;
const ref = ( 0 , external _wp _element _namespaceObject . useRef ) ( ) ;
2019-09-19 17:19:18 +02:00
2021-05-21 12:14:23 +02:00
function createRecord ( ) {
const {
ownerDocument : {
defaultView
}
} = ref . current ;
const selection = defaultView . getSelection ( ) ;
const range = selection . rangeCount > 0 ? selection . getRangeAt ( 0 ) : null ;
return create ( {
element : ref . current ,
range ,
multilineTag ,
multilineWrapperTags : multilineTag === 'li' ? [ 'ul' , 'ol' ] : undefined ,
_ _unstableIsEditableTree : true ,
preserveWhiteSpace
} ) ;
2020-06-26 15:33:47 +02:00
}
2019-09-19 17:19:18 +02:00
2023-06-27 16:24:19 +02:00
function applyRecord ( newRecord , {
domOnly
} = { } ) {
2021-05-21 12:14:23 +02:00
apply ( {
value : newRecord ,
current : ref . current ,
multilineTag ,
multilineWrapperTags : multilineTag === 'li' ? [ 'ul' , 'ol' ] : undefined ,
prepareEditableTree : _ _unstableAddInvisibleFormats ,
_ _unstableDomOnly : domOnly ,
placeholder
} ) ;
} // Internal values are updated synchronously, unlike props and state.
2019-09-19 17:19:18 +02:00
2022-04-11 14:04:30 +02:00
const _value = ( 0 , external _wp _element _namespaceObject . useRef ) ( value ) ;
2019-09-19 17:19:18 +02:00
2022-04-11 14:04:30 +02:00
const record = ( 0 , external _wp _element _namespaceObject . useRef ) ( ) ;
2019-09-19 17:19:18 +02:00
2021-05-21 12:14:23 +02:00
function setRecordFromProps ( ) {
_value . current = value ;
record . current = create ( {
html : value ,
multilineTag ,
multilineWrapperTags : multilineTag === 'li' ? [ 'ul' , 'ol' ] : undefined ,
preserveWhiteSpace
} ) ;
2019-09-19 17:19:18 +02:00
2021-05-21 12:14:23 +02:00
if ( disableFormats ) {
record . current . formats = Array ( value . length ) ;
record . current . replacements = Array ( value . length ) ;
2020-06-26 15:33:47 +02:00
}
2021-11-08 15:29:21 +01:00
if ( _ _unstableAfterParse ) {
record . current . formats = _ _unstableAfterParse ( record . current ) ;
}
2021-05-21 12:14:23 +02:00
record . current . start = selectionStart ;
record . current . end = selectionEnd ;
}
2019-09-19 17:19:18 +02:00
2022-04-11 14:04:30 +02:00
const hadSelectionUpdate = ( 0 , external _wp _element _namespaceObject . useRef ) ( false ) ;
2020-06-26 15:33:47 +02:00
2021-05-21 12:14:23 +02:00
if ( ! record . current ) {
2023-06-27 16:24:19 +02:00
hadSelectionUpdate . current = isSelected ;
2021-11-08 15:29:21 +01:00
setRecordFromProps ( ) ; // Sometimes formats are added programmatically and we need to make
// sure it's persisted to the block store / markup. If these formats
// are not applied, they could cause inconsistencies between the data
// in the visual editor and the frontend. Right now, it's only relevant
// to the `core/text-color` format, which is applied at runtime in
// certain circunstances. See the `__unstableFilterAttributeValue`
// function in `packages/format-library/src/text-color/index.js`.
// @todo find a less-hacky way of solving this.
2023-06-27 16:24:19 +02:00
const hasRelevantInitFormat = record . current ? . formats [ 0 ] ? . [ 0 ] ? . type === 'core/text-color' ;
2021-11-08 15:29:21 +01:00
if ( hasRelevantInitFormat ) {
handleChangesUponInit ( record . current ) ;
}
2021-05-21 12:14:23 +02:00
} else if ( selectionStart !== record . current . start || selectionEnd !== record . current . end ) {
hadSelectionUpdate . current = isSelected ;
record . current = { ... record . current ,
start : selectionStart ,
end : selectionEnd
2021-05-19 17:09:27 +02:00
} ;
2020-06-26 15:33:47 +02:00
}
/ * *
* Sync the value to global state . The node tree and selection will also be
* updated if differences are found .
*
2021-05-21 12:14:23 +02:00
* @ param { Object } newRecord The record to sync and apply .
2020-06-26 15:33:47 +02:00
* /
2021-05-21 12:14:23 +02:00
function handleChange ( newRecord ) {
2021-11-08 15:29:21 +01:00
record . current = newRecord ;
2021-05-21 12:14:23 +02:00
applyRecord ( newRecord ) ;
2020-06-26 15:33:47 +02:00
if ( disableFormats ) {
2021-05-21 12:14:23 +02:00
_value . current = newRecord . text ;
} else {
_value . current = toHTMLString ( {
2021-11-08 15:29:21 +01:00
value : _ _unstableBeforeSerialize ? { ... newRecord ,
2021-05-21 12:14:23 +02:00
formats : _ _unstableBeforeSerialize ( newRecord )
2021-11-08 15:29:21 +01:00
} : newRecord ,
2021-05-21 12:14:23 +02:00
multilineTag ,
preserveWhiteSpace
} ) ;
2019-09-19 17:19:18 +02:00
}
2021-05-19 17:09:27 +02:00
const {
start ,
end ,
2021-05-21 12:14:23 +02:00
formats ,
text
} = newRecord ; // Selection must be updated first, so it is recorded in history when
2020-06-26 15:33:47 +02:00
// the content change happens.
2021-11-08 15:29:21 +01:00
// We batch both calls to only attempt to rerender once.
registry . batch ( ( ) => {
onSelectionChange ( start , end ) ;
onChange ( _value . current , {
_ _unstableFormats : formats ,
_ _unstableText : text
} ) ;
} ) ;
forceRender ( ) ;
}
2020-06-26 15:33:47 +02:00
2021-11-08 15:29:21 +01:00
function handleChangesUponInit ( newRecord ) {
record . current = newRecord ;
_value . current = toHTMLString ( {
value : _ _unstableBeforeSerialize ? { ... newRecord ,
formats : _ _unstableBeforeSerialize ( newRecord )
} : newRecord ,
multilineTag ,
preserveWhiteSpace
} ) ;
const {
formats ,
text
} = newRecord ;
registry . batch ( ( ) => {
onChange ( _value . current , {
_ _unstableFormats : formats ,
_ _unstableText : text
} ) ;
2021-05-21 12:14:23 +02:00
} ) ;
forceRender ( ) ;
2020-06-26 15:33:47 +02:00
}
function applyFromProps ( ) {
2021-05-21 12:14:23 +02:00
setRecordFromProps ( ) ;
2020-06-26 15:33:47 +02:00
applyRecord ( record . current ) ;
}
2022-04-11 14:04:30 +02:00
const didMount = ( 0 , external _wp _element _namespaceObject . useRef ) ( false ) ; // Value updates must happen synchonously to avoid overwriting newer values.
2021-05-21 12:14:23 +02:00
2022-04-11 14:04:30 +02:00
( 0 , external _wp _element _namespaceObject . useLayoutEffect ) ( ( ) => {
2020-06-26 15:33:47 +02:00
if ( didMount . current && value !== _value . current ) {
applyFromProps ( ) ;
2022-04-12 17:12:47 +02:00
forceRender ( ) ;
2019-09-19 17:19:18 +02:00
}
2021-05-21 12:14:23 +02:00
} , [ value ] ) ; // Value updates must happen synchonously to avoid overwriting newer values.
2022-04-11 14:04:30 +02:00
( 0 , external _wp _element _namespaceObject . useLayoutEffect ) ( ( ) => {
2021-05-21 12:14:23 +02:00
if ( ! hadSelectionUpdate . current ) {
2020-06-26 15:33:47 +02:00
return ;
}
2022-04-12 17:12:47 +02:00
if ( ref . current . ownerDocument . activeElement !== ref . current ) {
ref . current . focus ( ) ;
}
2021-05-21 12:14:23 +02:00
applyFromProps ( ) ;
hadSelectionUpdate . current = false ;
} , [ hadSelectionUpdate . current ] ) ;
2022-04-11 14:04:30 +02:00
const mergedRefs = ( 0 , external _wp _compose _namespaceObject . useMergeRefs ) ( [ ref , useDefaultStyle ( ) , useBoundaryStyle ( {
2021-05-21 12:14:23 +02:00
record
2021-11-08 15:29:21 +01:00
} ) , useCopyHandler ( {
2021-05-21 12:14:23 +02:00
record ,
multilineTag ,
preserveWhiteSpace
} ) , useSelectObject ( ) , useFormatBoundaries ( {
record ,
applyRecord
} ) , useDelete ( {
createRecord ,
handleChange ,
multilineTag
} ) , useInputAndSelection ( {
record ,
applyRecord ,
createRecord ,
handleChange ,
2021-05-19 17:09:27 +02:00
isSelected ,
2021-05-21 12:14:23 +02:00
onSelectionChange
2023-06-27 16:24:19 +02:00
} ) , useSelectionChangeCompat ( ) , ( 0 , external _wp _compose _namespaceObject . useRefEffect ) ( ( ) => {
2021-05-21 12:14:23 +02:00
applyFromProps ( ) ;
didMount . current = true ;
} , [ placeholder , ... _ _unstableDependencies ] ) ] ) ;
return {
2020-06-26 15:33:47 +02:00
value : record . current ,
Editor: Update block editor packages to the latest patch releases.
This updates the block editor related npm dependencies to their latest patch versions ahead of WordPress 6.2.1 RC1.
Updated packages:
- @wordpress/annotations@2.26.4
- @wordpress/block-directory@4.3.12
- @wordpress/block-editor@11.3.10
- @wordpress/block-library@8.3.12
- @wordpress/components@23.3.7
- @wordpress/customize-widgets@4.3.12
- @wordpress/edit-post@7.3.12
- @wordpress/edit-site@5.3.12
- @wordpress/edit-widgets@5.3.12
- @wordpress/editor@13.3.10
- @wordpress/format-library@4.3.10
- @wordpress/interface@5.3.8
- @wordpress/list-reusable-blocks@4.3.7
- @wordpress/preferences@3.3.7
- @wordpress/reusable-blocks@4.3.10
- @wordpress/rich-text@6.3.4
- @wordpress/server-side-render@4.3.7
- @wordpress/widgets@3.3.10
This changeset includes the following fixes:
- i18n: Add context to labels related to CSS position properties gutenberg#49135
- Comments: Fix 'sprintf requires more than 1 params' error gutenberg#49054
- Fix the site editor loading in multi-site installs gutenberg#49861
- Fix quick inserter going off-screen in some situations gutenberg#49881
- Site Editor: Decode the site title properly gutenberg#49685
- Firefox: fix input rules (React async state issue) gutenberg#48210
- Only show alignment info when parent layout is constrained. gutenberg#49703
- [Inserter]: Fix onHover error on patterns tab in mobile gutenberg#49450
- Fix site editor redirection after creating new template or template part gutenberg#49364
Props mamaduka, audrasjb, wildworks, ocean90, aristath, costdev, hellofromtonya, youknowriad, mdxfr, oandregal, mattwiebe, bph, ndiego, talldanwp, joen, ellatrix, kevin940726, isabel_brison, andrewserong, ntsekouras, welcher.
Fixes #58274.
Built from https://develop.svn.wordpress.org/trunk@55737
git-svn-id: http://core.svn.wordpress.org/trunk@55249 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2023-05-09 16:13:25 +02:00
// A function to get the most recent value so event handlers in
// useRichText implementations have access to it. For example when
// listening to input events, we internally update the state, but this
// state is not yet available to the input event handler because React
// may re-render asynchronously.
getValue : ( ) => record . current ,
2020-06-26 15:33:47 +02:00
onChange : handleChange ,
2021-05-21 12:14:23 +02:00
ref : mergedRefs
} ;
2020-06-26 15:33:47 +02:00
}
2021-05-21 12:14:23 +02:00
function _ _experimentalRichText ( ) { }
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/format-edit.js
2021-05-21 12:14:23 +02:00
2019-10-15 17:37:08 +02:00
/ * *
2021-05-21 12:14:23 +02:00
* Internal dependencies
2019-10-15 17:37:08 +02:00
* /
2020-10-13 15:10:30 +02:00
2023-06-27 16:24:19 +02:00
function FormatEdit ( {
formatTypes ,
onChange ,
onFocus ,
value ,
forwardedRef
} ) {
2021-05-21 12:14:23 +02:00
return formatTypes . map ( settings => {
const {
name ,
edit : Edit
} = settings ;
if ( ! Edit ) {
return null ;
}
const activeFormat = getActiveFormat ( value , name ) ;
const isActive = activeFormat !== undefined ;
const activeObject = getActiveObject ( value ) ;
const isObjectActive = activeObject !== undefined && activeObject . type === name ;
2022-04-11 14:04:30 +02:00
return ( 0 , external _wp _element _namespaceObject . createElement ) ( Edit , {
2021-05-21 12:14:23 +02:00
key : name ,
isActive : isActive ,
activeAttributes : isActive ? activeFormat . attributes || { } : { } ,
isObjectActive : isObjectActive ,
activeObjectAttributes : isObjectActive ? activeObject . attributes || { } : { } ,
value : value ,
onChange : onChange ,
onFocus : onFocus ,
contentRef : forwardedRef
} ) ;
} ) ;
}
2019-10-15 17:37:08 +02:00
2022-04-11 14:04:30 +02:00
; // CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/index.js
2019-09-19 17:19:18 +02:00
2019-10-15 17:37:08 +02:00
2019-09-19 17:19:18 +02:00
2021-04-15 17:19:43 +02:00
2023-06-27 16:24:19 +02:00
/ * *
* An object which represents a formatted string . See main ` @wordpress/rich-text `
* documentation for more information .
* /
2018-12-14 05:41:57 +01:00
2022-04-11 14:04:30 +02:00
( window . wp = window . wp || { } ) . richText = _ _webpack _exports _ _ ;
/******/ } ) ( )
;