Preview: block-editor.js
Size: 2.60 MB
/home/jambtst2015/public_html/cccng.org/wp-includes/js/dist/block-editor.js
/******/ (() => { // webpackBootstrap
/******/ var __webpack_modules__ = ({
/***/ 197:
/***/ (() => {
/* (ignored) */
/***/ }),
/***/ 271:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
let Container = __webpack_require__(683)
let LazyResult, Processor
class Document extends Container {
constructor(defaults) {
// type needs to be passed to super, otherwise child roots won't be normalized correctly
super({ type: 'document', ...defaults })
if (!this.nodes) {
this.nodes = []
}
}
toResult(opts = {}) {
let lazy = new LazyResult(new Processor(), this, opts)
return lazy.stringify()
}
}
Document.registerLazyResult = dependant => {
LazyResult = dependant
}
Document.registerProcessor = dependant => {
Processor = dependant
}
module.exports = Document
Document.default = Document
/***/ }),
/***/ 346:
/***/ ((module) => {
"use strict";
const DEFAULT_RAW = {
after: '\n',
beforeClose: '\n',
beforeComment: '\n',
beforeDecl: '\n',
beforeOpen: ' ',
beforeRule: '\n',
colon: ': ',
commentLeft: ' ',
commentRight: ' ',
emptyBody: '',
indent: ' ',
semicolon: false
}
function capitalize(str) {
return str[0].toUpperCase() + str.slice(1)
}
class Stringifier {
constructor(builder) {
this.builder = builder
}
atrule(node, semicolon) {
let name = '@' + node.name
let params = node.params ? this.rawValue(node, 'params') : ''
if (typeof node.raws.afterName !== 'undefined') {
name += node.raws.afterName
} else if (params) {
name += ' '
}
if (node.nodes) {
this.block(node, name + params)
} else {
let end = (node.raws.between || '') + (semicolon ? ';' : '')
this.builder(name + params + end, node)
}
}
beforeAfter(node, detect) {
let value
if (node.type === 'decl') {
value = this.raw(node, null, 'beforeDecl')
} else if (node.type === 'comment') {
value = this.raw(node, null, 'beforeComment')
} else if (detect === 'before') {
value = this.raw(node, null, 'beforeRule')
} else {
value = this.raw(node, null, 'beforeClose')
}
let buf = node.parent
let depth = 0
while (buf && buf.type !== 'root') {
depth += 1
buf = buf.parent
}
if (value.includes('\n')) {
let indent = this.raw(node, null, 'indent')
if (indent.length) {
for (let step = 0; step < depth; step++) value += indent
}
}
return value
}
block(node, start) {
let between = this.raw(node, 'between', 'beforeOpen')
this.builder(start + between + '{', node, 'start')
let after
if (node.nodes && node.nodes.length) {
this.body(node)
after = this.raw(node, 'after')
} else {
after = this.raw(node, 'after', 'emptyBody')
}
if (after) this.builder(after)
this.builder('}', node, 'end')
}
body(node) {
let last = node.nodes.length - 1
while (last > 0) {
if (node.nodes[last].type !== 'comment') break
last -= 1
}
let semicolon = this.raw(node, 'semicolon')
for (let i = 0; i < node.nodes.length; i++) {
let child = node.nodes[i]
let before = this.raw(child, 'before')
if (before) this.builder(before)
this.stringify(child, last !== i || semicolon)
}
}
comment(node) {
let left = this.raw(node, 'left', 'commentLeft')
let right = this.raw(node, 'right', 'commentRight')
this.builder('/*' + left + node.text + right + '*/', node)
}
decl(node, semicolon) {
let between = this.raw(node, 'between', 'colon')
let string = node.prop + between + this.rawValue(node, 'value')
if (node.important) {
string += node.raws.important || ' !important'
}
if (semicolon) string += ';'
this.builder(string, node)
}
document(node) {
this.body(node)
}
raw(node, own, detect) {
let value
if (!detect) detect = own
// Already had
if (own) {
value = node.raws[own]
if (typeof value !== 'undefined') return value
}
let parent = node.parent
if (detect === 'before') {
// Hack for first rule in CSS
if (!parent || (parent.type === 'root' && parent.first === node)) {
return ''
}
// `root` nodes in `document` should use only their own raws
if (parent && parent.type === 'document') {
return ''
}
}
// Floating child without parent
if (!parent) return DEFAULT_RAW[detect]
// Detect style by other nodes
let root = node.root()
if (!root.rawCache) root.rawCache = {}
if (typeof root.rawCache[detect] !== 'undefined') {
return root.rawCache[detect]
}
if (detect === 'before' || detect === 'after') {
return this.beforeAfter(node, detect)
} else {
let method = 'raw' + capitalize(detect)
if (this[method]) {
value = this[method](root, node)
} else {
root.walk(i => {
value = i.raws[own]
if (typeof value !== 'undefined') return false
})
}
}
if (typeof value === 'undefined') value = DEFAULT_RAW[detect]
root.rawCache[detect] = value
return value
}
rawBeforeClose(root) {
let value
root.walk(i => {
if (i.nodes && i.nodes.length > 0) {
if (typeof i.raws.after !== 'undefined') {
value = i.raws.after
if (value.includes('\n')) {
value = value.replace(/[^\n]+$/, '')
}
return false
}
}
})
if (value) value = value.replace(/\S/g, '')
return value
}
rawBeforeComment(root, node) {
let value
root.walkComments(i => {
if (typeof i.raws.before !== 'undefined') {
value = i.raws.before
if (value.includes('\n')) {
value = value.replace(/[^\n]+$/, '')
}
return false
}
})
if (typeof value === 'undefined') {
value = this.raw(node, null, 'beforeDecl')
} else if (value) {
value = value.replace(/\S/g, '')
}
return value
}
rawBeforeDecl(root, node) {
let value
root.walkDecls(i => {
if (typeof i.raws.before !== 'undefined') {
value = i.raws.before
if (value.includes('\n')) {
value = value.replace(/[^\n]+$/, '')
}
return false
}
})
if (typeof value === 'undefined') {
value = this.raw(node, null, 'beforeRule')
} else if (value) {
value = value.replace(/\S/g, '')
}
return value
}
rawBeforeOpen(root) {
let value
root.walk(i => {
if (i.type !== 'decl') {
value = i.raws.between
if (typeof value !== 'undefined') return false
}
})
return value
}
rawBeforeRule(root) {
let value
root.walk(i => {
if (i.nodes && (i.parent !== root || root.first !== i)) {
if (typeof i.raws.before !== 'undefined') {
value = i.raws.before
if (value.includes('\n')) {
value = value.replace(/[^\n]+$/, '')
}
return false
}
}
})
if (value) value = value.replace(/\S/g, '')
return value
}
rawColon(root) {
let value
root.walkDecls(i => {
if (typeof i.raws.between !== 'undefined') {
value = i.raws.between.replace(/[^\s:]/g, '')
return false
}
})
return value
}
rawEmptyBody(root) {
let value
root.walk(i => {
if (i.nodes && i.nodes.length === 0) {
value = i.raws.after
if (typeof value !== 'undefined') return false
}
})
return value
}
rawIndent(root) {
if (root.raws.indent) return root.raws.indent
let value
root.walk(i => {
let p = i.parent
if (p && p !== root && p.parent && p.parent === root) {
if (typeof i.raws.before !== 'undefined') {
let parts = i.raws.before.split('\n')
value = parts[parts.length - 1]
value = value.replace(/\S/g, '')
return false
}
}
})
return value
}
rawSemicolon(root) {
let value
root.walk(i => {
if (i.nodes && i.nodes.length && i.last.type === 'decl') {
value = i.raws.semicolon
if (typeof value !== 'undefined') return false
}
})
return value
}
rawValue(node, prop) {
let value = node[prop]
let raw = node.raws[prop]
if (raw && raw.value === value) {
return raw.raw
}
return value
}
root(node) {
this.body(node)
if (node.raws.after) this.builder(node.raws.after)
}
rule(node) {
this.block(node, this.rawValue(node, 'selector'))
if (node.raws.ownSemicolon) {
this.builder(node.raws.ownSemicolon, node, 'end')
}
}
stringify(node, semicolon) {
/* c8 ignore start */
if (!this[node.type]) {
throw new Error(
'Unknown AST node type ' +
node.type +
'. ' +
'Maybe you need to change PostCSS stringifier.'
)
}
/* c8 ignore stop */
this[node.type](node, semicolon)
}
}
module.exports = Stringifier
Stringifier.default = Stringifier
/***/ }),
/***/ 356:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
let pico = __webpack_require__(2775)
let terminalHighlight = __webpack_require__(9746)
class CssSyntaxError extends Error {
constructor(message, line, column, source, file, plugin) {
super(message)
this.name = 'CssSyntaxError'
this.reason = message
if (file) {
this.file = file
}
if (source) {
this.source = source
}
if (plugin) {
this.plugin = plugin
}
if (typeof line !== 'undefined' && typeof column !== 'undefined') {
if (typeof line === 'number') {
this.line = line
this.column = column
} else {
this.line = line.line
this.column = line.column
this.endLine = column.line
this.endColumn = column.column
}
}
this.setMessage()
if (Error.captureStackTrace) {
Error.captureStackTrace(this, CssSyntaxError)
}
}
setMessage() {
this.message = this.plugin ? this.plugin + ': ' : ''
this.message += this.file ? this.file : '<css input>'
if (typeof this.line !== 'undefined') {
this.message += ':' + this.line + ':' + this.column
}
this.message += ': ' + this.reason
}
showSourceCode(color) {
if (!this.source) return ''
let css = this.source
if (color == null) color = pico.isColorSupported
let aside = text => text
let mark = text => text
let highlight = text => text
if (color) {
let { bold, gray, red } = pico.createColors(true)
mark = text => bold(red(text))
aside = text => gray(text)
if (terminalHighlight) {
highlight = text => terminalHighlight(text)
}
}
let lines = css.split(/\r?\n/)
let start = Math.max(this.line - 3, 0)
let end = Math.min(this.line + 2, lines.length)
let maxWidth = String(end).length
return lines
.slice(start, end)
.map((line, index) => {
let number = start + 1 + index
let gutter = ' ' + (' ' + number).slice(-maxWidth) + ' | '
if (number === this.line) {
if (line.length > 160) {
let padding = 20
let subLineStart = Math.max(0, this.column - padding)
let subLineEnd = Math.max(
this.column + padding,
this.endColumn + padding
)
let subLine = line.slice(subLineStart, subLineEnd)
let spacing =
aside(gutter.replace(/\d/g, ' ')) +
line
.slice(0, Math.min(this.column - 1, padding - 1))
.replace(/[^\t]/g, ' ')
return (
mark('>') +
aside(gutter) +
highlight(subLine) +
'\n ' +
spacing +
mark('^')
)
}
let spacing =
aside(gutter.replace(/\d/g, ' ')) +
line.slice(0, this.column - 1).replace(/[^\t]/g, ' ')
return (
mark('>') +
aside(gutter) +
highlight(line) +
'\n ' +
spacing +
mark('^')
)
}
return ' ' + aside(gutter) + highlight(line)
})
.join('\n')
}
toString() {
let code = this.showSourceCode()
if (code) {
code = '\n\n' + code + '\n'
}
return this.name + ': ' + this.message + code
}
}
module.exports = CssSyntaxError
CssSyntaxError.default = CssSyntaxError
/***/ }),
/***/ 448:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
let Container = __webpack_require__(683)
let Document = __webpack_require__(271)
let MapGenerator = __webpack_require__(1670)
let parse = __webpack_require__(4295)
let Result = __webpack_require__(9055)
let Root = __webpack_require__(9434)
let stringify = __webpack_require__(633)
let { isClean, my } = __webpack_require__(1381)
let warnOnce = __webpack_require__(3122)
const TYPE_TO_CLASS_NAME = {
atrule: 'AtRule',
comment: 'Comment',
decl: 'Declaration',
document: 'Document',
root: 'Root',
rule: 'Rule'
}
const PLUGIN_PROPS = {
AtRule: true,
AtRuleExit: true,
Comment: true,
CommentExit: true,
Declaration: true,
DeclarationExit: true,
Document: true,
DocumentExit: true,
Once: true,
OnceExit: true,
postcssPlugin: true,
prepare: true,
Root: true,
RootExit: true,
Rule: true,
RuleExit: true
}
const NOT_VISITORS = {
Once: true,
postcssPlugin: true,
prepare: true
}
const CHILDREN = 0
function isPromise(obj) {
return typeof obj === 'object' && typeof obj.then === 'function'
}
function getEvents(node) {
let key = false
let type = TYPE_TO_CLASS_NAME[node.type]
if (node.type === 'decl') {
key = node.prop.toLowerCase()
} else if (node.type === 'atrule') {
key = node.name.toLowerCase()
}
if (key && node.append) {
return [
type,
type + '-' + key,
CHILDREN,
type + 'Exit',
type + 'Exit-' + key
]
} else if (key) {
return [type, type + '-' + key, type + 'Exit', type + 'Exit-' + key]
} else if (node.append) {
return [type, CHILDREN, type + 'Exit']
} else {
return [type, type + 'Exit']
}
}
function toStack(node) {
let events
if (node.type === 'document') {
events = ['Document', CHILDREN, 'DocumentExit']
} else if (node.type === 'root') {
events = ['Root', CHILDREN, 'RootExit']
} else {
events = getEvents(node)
}
return {
eventIndex: 0,
events,
iterator: 0,
node,
visitorIndex: 0,
visitors: []
}
}
function cleanMarks(node) {
node[isClean] = false
if (node.nodes) node.nodes.forEach(i => cleanMarks(i))
return node
}
let postcss = {}
class LazyResult {
get content() {
return this.stringify().content
}
get css() {
return this.stringify().css
}
get map() {
return this.stringify().map
}
get messages() {
return this.sync().messages
}
get opts() {
return this.result.opts
}
get processor() {
return this.result.processor
}
get root() {
return this.sync().root
}
get [Symbol.toStringTag]() {
return 'LazyResult'
}
constructor(processor, css, opts) {
this.stringified = false
this.processed = false
let root
if (
typeof css === 'object' &&
css !== null &&
(css.type === 'root' || css.type === 'document')
) {
root = cleanMarks(css)
} else if (css instanceof LazyResult || css instanceof Result) {
root = cleanMarks(css.root)
if (css.map) {
if (typeof opts.map === 'undefined') opts.map = {}
if (!opts.map.inline) opts.map.inline = false
opts.map.prev = css.map
}
} else {
let parser = parse
if (opts.syntax) parser = opts.syntax.parse
if (opts.parser) parser = opts.parser
if (parser.parse) parser = parser.parse
try {
root = parser(css, opts)
} catch (error) {
this.processed = true
this.error = error
}
if (root && !root[my]) {
/* c8 ignore next 2 */
Container.rebuild(root)
}
}
this.result = new Result(processor, root, opts)
this.helpers = { ...postcss, postcss, result: this.result }
this.plugins = this.processor.plugins.map(plugin => {
if (typeof plugin === 'object' && plugin.prepare) {
return { ...plugin, ...plugin.prepare(this.result) }
} else {
return plugin
}
})
}
async() {
if (this.error) return Promise.reject(this.error)
if (this.processed) return Promise.resolve(this.result)
if (!this.processing) {
this.processing = this.runAsync()
}
return this.processing
}
catch(onRejected) {
return this.async().catch(onRejected)
}
finally(onFinally) {
return this.async().then(onFinally, onFinally)
}
getAsyncError() {
throw new Error('Use process(css).then(cb) to work with async plugins')
}
handleError(error, node) {
let plugin = this.result.lastPlugin
try {
if (node) node.addToError(error)
this.error = error
if (error.name === 'CssSyntaxError' && !error.plugin) {
error.plugin = plugin.postcssPlugin
error.setMessage()
} else if (plugin.postcssVersion) {
if (false) {}
}
} catch (err) {
/* c8 ignore next 3 */
// eslint-disable-next-line no-console
if (console && console.error) console.error(err)
}
return error
}
prepareVisitors() {
this.listeners = {}
let add = (plugin, type, cb) => {
if (!this.listeners[type]) this.listeners[type] = []
this.listeners[type].push([plugin, cb])
}
for (let plugin of this.plugins) {
if (typeof plugin === 'object') {
for (let event in plugin) {
if (!PLUGIN_PROPS[event] && /^[A-Z]/.test(event)) {
throw new Error(
`Unknown event ${event} in ${plugin.postcssPlugin}. ` +
`Try to update PostCSS (${this.processor.version} now).`
)
}
if (!NOT_VISITORS[event]) {
if (typeof plugin[event] === 'object') {
for (let filter in plugin[event]) {
if (filter === '*') {
add(plugin, event, plugin[event][filter])
} else {
add(
plugin,
event + '-' + filter.toLowerCase(),
plugin[event][filter]
)
}
}
} else if (typeof plugin[event] === 'function') {
add(plugin, event, plugin[event])
}
}
}
}
}
this.hasListener = Object.keys(this.listeners).length > 0
}
async runAsync() {
this.plugin = 0
for (let i = 0; i < this.plugins.length; i++) {
let plugin = this.plugins[i]
let promise = this.runOnRoot(plugin)
if (isPromise(promise)) {
try {
await promise
} catch (error) {
throw this.handleError(error)
}
}
}
this.prepareVisitors()
if (this.hasListener) {
let root = this.result.root
while (!root[isClean]) {
root[isClean] = true
let stack = [toStack(root)]
while (stack.length > 0) {
let promise = this.visitTick(stack)
if (isPromise(promise)) {
try {
await promise
} catch (e) {
let node = stack[stack.length - 1].node
throw this.handleError(e, node)
}
}
}
}
if (this.listeners.OnceExit) {
for (let [plugin, visitor] of this.listeners.OnceExit) {
this.result.lastPlugin = plugin
try {
if (root.type === 'document') {
let roots = root.nodes.map(subRoot =>
visitor(subRoot, this.helpers)
)
await Promise.all(roots)
} else {
await visitor(root, this.helpers)
}
} catch (e) {
throw this.handleError(e)
}
}
}
}
this.processed = true
return this.stringify()
}
runOnRoot(plugin) {
this.result.lastPlugin = plugin
try {
if (typeof plugin === 'object' && plugin.Once) {
if (this.result.root.type === 'document') {
let roots = this.result.root.nodes.map(root =>
plugin.Once(root, this.helpers)
)
if (isPromise(roots[0])) {
return Promise.all(roots)
}
return roots
}
return plugin.Once(this.result.root, this.helpers)
} else if (typeof plugin === 'function') {
return plugin(this.result.root, this.result)
}
} catch (error) {
throw this.handleError(error)
}
}
stringify() {
if (this.error) throw this.error
if (this.stringified) return this.result
this.stringified = true
this.sync()
let opts = this.result.opts
let str = stringify
if (opts.syntax) str = opts.syntax.stringify
if (opts.stringifier) str = opts.stringifier
if (str.stringify) str = str.stringify
let map = new MapGenerator(str, this.result.root, this.result.opts)
let data = map.generate()
this.result.css = data[0]
this.result.map = data[1]
return this.result
}
sync() {
if (this.error) throw this.error
if (this.processed) return this.result
this.processed = true
if (this.processing) {
throw this.getAsyncError()
}
for (let plugin of this.plugins) {
let promise = this.runOnRoot(plugin)
if (isPromise(promise)) {
throw this.getAsyncError()
}
}
this.prepareVisitors()
if (this.hasListener) {
let root = this.result.root
while (!root[isClean]) {
root[isClean] = true
this.walkSync(root)
}
if (this.listeners.OnceExit) {
if (root.type === 'document') {
for (let subRoot of root.nodes) {
this.visitSync(this.listeners.OnceExit, subRoot)
}
} else {
this.visitSync(this.listeners.OnceExit, root)
}
}
}
return this.result
}
then(onFulfilled, onRejected) {
if (false) {}
return this.async().then(onFulfilled, onRejected)
}
toString() {
return this.css
}
visitSync(visitors, node) {
for (let [plugin, visitor] of visitors) {
this.result.lastPlugin = plugin
let promise
try {
promise = visitor(node, this.helpers)
} catch (e) {
throw this.handleError(e, node.proxyOf)
}
if (node.type !== 'root' && node.type !== 'document' && !node.parent) {
return true
}
if (isPromise(promise)) {
throw this.getAsyncError()
}
}
}
visitTick(stack) {
let visit = stack[stack.length - 1]
let { node, visitors } = visit
if (node.type !== 'root' && node.type !== 'document' && !node.parent) {
stack.pop()
return
}
if (visitors.length > 0 && visit.visitorIndex < visitors.length) {
let [plugin, visitor] = visitors[visit.visitorIndex]
visit.visitorIndex += 1
if (visit.visitorIndex === visitors.length) {
visit.visitors = []
visit.visitorIndex = 0
}
this.result.lastPlugin = plugin
try {
return visitor(node.toProxy(), this.helpers)
} catch (e) {
throw this.handleError(e, node)
}
}
if (visit.iterator !== 0) {
let iterator = visit.iterator
let child
while ((child = node.nodes[node.indexes[iterator]])) {
node.indexes[iterator] += 1
if (!child[isClean]) {
child[isClean] = true
stack.push(toStack(child))
return
}
}
visit.iterator = 0
delete node.indexes[iterator]
}
let events = visit.events
while (visit.eventIndex < events.length) {
let event = events[visit.eventIndex]
visit.eventIndex += 1
if (event === CHILDREN) {
if (node.nodes && node.nodes.length) {
node[isClean] = true
visit.iterator = node.getIterator()
}
return
} else if (this.listeners[event]) {
visit.visitors = this.listeners[event]
return
}
}
stack.pop()
}
walkSync(node) {
node[isClean] = true
let events = getEvents(node)
for (let event of events) {
if (event === CHILDREN) {
if (node.nodes) {
node.each(child => {
if (!child[isClean]) this.walkSync(child)
})
}
} else {
let visitors = this.listeners[event]
if (visitors) {
if (this.visitSync(visitors, node.toProxy())) return
}
}
}
}
warnings() {
return this.sync().warnings()
}
}
LazyResult.registerPostcss = dependant => {
postcss = dependant
}
module.exports = LazyResult
LazyResult.default = LazyResult
Root.registerLazyResult(LazyResult)
Document.registerLazyResult(LazyResult)
/***/ }),
/***/ 461:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
// Load in dependencies
var computedStyle = __webpack_require__(6109);
/**
* Calculate the `line-height` of a given node
* @param {HTMLElement} node Element to calculate line height of. Must be in the DOM.
* @returns {Number} `line-height` of the element in pixels
*/
function lineHeight(node) {
// Grab the line-height via style
var lnHeightStr = computedStyle(node, 'line-height');
var lnHeight = parseFloat(lnHeightStr, 10);
// If the lineHeight did not contain a unit (i.e. it was numeric), convert it to ems (e.g. '2.3' === '2.3em')
if (lnHeightStr === lnHeight + '') {
// Save the old lineHeight style and update the em unit to the element
var _lnHeightStyle = node.style.lineHeight;
node.style.lineHeight = lnHeightStr + 'em';
// Calculate the em based height
lnHeightStr = computedStyle(node, 'line-height');
lnHeight = parseFloat(lnHeightStr, 10);
// Revert the lineHeight style
if (_lnHeightStyle) {
node.style.lineHeight = _lnHeightStyle;
} else {
delete node.style.lineHeight;
}
}
// If the lineHeight is in `pt`, convert it to pixels (4px for 3pt)
// DEV: `em` units are converted to `pt` in IE6
// Conversion ratio from https://developer.mozilla.org/en-US/docs/Web/CSS/length
if (lnHeightStr.indexOf('pt') !== -1) {
lnHeight *= 4;
lnHeight /= 3;
// Otherwise, if the lineHeight is in `mm`, convert it to pixels (96px for 25.4mm)
} else if (lnHeightStr.indexOf('mm') !== -1) {
lnHeight *= 96;
lnHeight /= 25.4;
// Otherwise, if the lineHeight is in `cm`, convert it to pixels (96px for 2.54cm)
} else if (lnHeightStr.indexOf('cm') !== -1) {
lnHeight *= 96;
lnHeight /= 2.54;
// Otherwise, if the lineHeight is in `in`, convert it to pixels (96px for 1in)
} else if (lnHeightStr.indexOf('in') !== -1) {
lnHeight *= 96;
// Otherwise, if the lineHeight is in `pc`, convert it to pixels (12pt for 1pc)
} else if (lnHeightStr.indexOf('pc') !== -1) {
lnHeight *= 16;
}
// Continue our computation
lnHeight = Math.round(lnHeight);
// If the line-height is "normal", calculate by font-size
if (lnHeightStr === 'normal') {
// Create a temporary node
var nodeName = node.nodeName;
var _node = document.createElement(nodeName);
_node.innerHTML = ' ';
// If we have a text area, reset it to only 1 row
// https://github.com/twolfson/line-height/issues/4
if (nodeName.toUpperCase() === 'TEXTAREA') {
_node.setAttribute('rows', '1');
}
// Set the font-size of the element
var fontSizeStr = computedStyle(node, 'font-size');
_node.style.fontSize = fontSizeStr;
// Remove default padding/border which can affect offset height
// https://github.com/twolfson/line-height/issues/4
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetHeight
_node.style.padding = '0px';
_node.style.border = '0px';
// Append it to the body
var body = document.body;
body.appendChild(_node);
// Assume the line height of the element is the height
var height = _node.offsetHeight;
lnHeight = height;
// Remove our child from the DOM
body.removeChild(_node);
}
// Return the calculated height
return lnHeight;
}
// Export lineHeight
module.exports = lineHeight;
/***/ }),
/***/ 628:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
var ReactPropTypesSecret = __webpack_require__(4067);
function emptyFunction() {}
function emptyFunctionWithReset() {}
emptyFunctionWithReset.resetWarningCache = emptyFunction;
module.exports = function() {
function shim(props, propName, componentName, location, propFullName, secret) {
if (secret === ReactPropTypesSecret) {
// It is still safe when called from React.
return;
}
var err = new Error(
'Calling PropTypes validators directly is not supported by the `prop-types` package. ' +
'Use PropTypes.checkPropTypes() to call them. ' +
'Read more at http://fb.me/use-check-prop-types'
);
err.name = 'Invariant Violation';
throw err;
};
shim.isRequired = shim;
function getShim() {
return shim;
};
// Important!
// Keep this list in sync with production version in `./factoryWithTypeCheckers.js`.
var ReactPropTypes = {
array: shim,
bigint: shim,
bool: shim,
func: shim,
number: shim,
object: shim,
string: shim,
symbol: shim,
any: shim,
arrayOf: getShim,
element: shim,
elementType: shim,
instanceOf: getShim,
node: shim,
objectOf: getShim,
oneOf: getShim,
oneOfType: getShim,
shape: getShim,
exact: getShim,
checkPropTypes: emptyFunctionWithReset,
resetWarningCache: emptyFunction
};
ReactPropTypes.PropTypes = ReactPropTypes;
return ReactPropTypes;
};
/***/ }),
/***/ 633:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
let Stringifier = __webpack_require__(346)
function stringify(node, builder) {
let str = new Stringifier(builder)
str.stringify(node)
}
module.exports = stringify
stringify.default = stringify
/***/ }),
/***/ 683:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
let Comment = __webpack_require__(6589)
let Declaration = __webpack_require__(1516)
let Node = __webpack_require__(7490)
let { isClean, my } = __webpack_require__(1381)
let AtRule, parse, Root, Rule
function cleanSource(nodes) {
return nodes.map(i => {
if (i.nodes) i.nodes = cleanSource(i.nodes)
delete i.source
return i
})
}
function markTreeDirty(node) {
node[isClean] = false
if (node.proxyOf.nodes) {
for (let i of node.proxyOf.nodes) {
markTreeDirty(i)
}
}
}
class Container extends Node {
get first() {
if (!this.proxyOf.nodes) return undefined
return this.proxyOf.nodes[0]
}
get last() {
if (!this.proxyOf.nodes) return undefined
return this.proxyOf.nodes[this.proxyOf.nodes.length - 1]
}
append(...children) {
for (let child of children) {
let nodes = this.normalize(child, this.last)
for (let node of nodes) this.proxyOf.nodes.push(node)
}
this.markDirty()
return this
}
cleanRaws(keepBetween) {
super.cleanRaws(keepBetween)
if (this.nodes) {
for (let node of this.nodes) node.cleanRaws(keepBetween)
}
}
each(callback) {
if (!this.proxyOf.nodes) return undefined
let iterator = this.getIterator()
let index, result
while (this.indexes[iterator] < this.proxyOf.nodes.length) {
index = this.indexes[iterator]
result = callback(this.proxyOf.nodes[index], index)
if (result === false) break
this.indexes[iterator] += 1
}
delete this.indexes[iterator]
return result
}
every(condition) {
return this.nodes.every(condition)
}
getIterator() {
if (!this.lastEach) this.lastEach = 0
if (!this.indexes) this.indexes = {}
this.lastEach += 1
let iterator = this.lastEach
this.indexes[iterator] = 0
return iterator
}
getProxyProcessor() {
return {
get(node, prop) {
if (prop === 'proxyOf') {
return node
} else if (!node[prop]) {
return node[prop]
} else if (
prop === 'each' ||
(typeof prop === 'string' && prop.startsWith('walk'))
) {
return (...args) => {
return node[prop](
...args.map(i => {
if (typeof i === 'function') {
return (child, index) => i(child.toProxy(), index)
} else {
return i
}
})
)
}
} else if (prop === 'every' || prop === 'some') {
return cb => {
return node[prop]((child, ...other) =>
cb(child.toProxy(), ...other)
)
}
} else if (prop === 'root') {
return () => node.root().toProxy()
} else if (prop === 'nodes') {
return node.nodes.map(i => i.toProxy())
} else if (prop === 'first' || prop === 'last') {
return node[prop].toProxy()
} else {
return node[prop]
}
},
set(node, prop, value) {
if (node[prop] === value) return true
node[prop] = value
if (prop === 'name' || prop === 'params' || prop === 'selector') {
node.markDirty()
}
return true
}
}
}
index(child) {
if (typeof child === 'number') return child
if (child.proxyOf) child = child.proxyOf
return this.proxyOf.nodes.indexOf(child)
}
insertAfter(exist, add) {
let existIndex = this.index(exist)
let nodes = this.normalize(add, this.proxyOf.nodes[existIndex]).reverse()
existIndex = this.index(exist)
for (let node of nodes) this.proxyOf.nodes.splice(existIndex + 1, 0, node)
let index
for (let id in this.indexes) {
index = this.indexes[id]
if (existIndex < index) {
this.indexes[id] = index + nodes.length
}
}
this.markDirty()
return this
}
insertBefore(exist, add) {
let existIndex = this.index(exist)
let type = existIndex === 0 ? 'prepend' : false
let nodes = this.normalize(
add,
this.proxyOf.nodes[existIndex],
type
).reverse()
existIndex = this.index(exist)
for (let node of nodes) this.proxyOf.nodes.splice(existIndex, 0, node)
let index
for (let id in this.indexes) {
index = this.indexes[id]
if (existIndex <= index) {
this.indexes[id] = index + nodes.length
}
}
this.markDirty()
return this
}
normalize(nodes, sample) {
if (typeof nodes === 'string') {
nodes = cleanSource(parse(nodes).nodes)
} else if (typeof nodes === 'undefined') {
nodes = []
} else if (Array.isArray(nodes)) {
nodes = nodes.slice(0)
for (let i of nodes) {
if (i.parent) i.parent.removeChild(i, 'ignore')
}
} else if (nodes.type === 'root' && this.type !== 'document') {
nodes = nodes.nodes.slice(0)
for (let i of nodes) {
if (i.parent) i.parent.removeChild(i, 'ignore')
}
} else if (nodes.type) {
nodes = [nodes]
} else if (nodes.prop) {
if (typeof nodes.value === 'undefined') {
throw new Error('Value field is missed in node creation')
} else if (typeof nodes.value !== 'string') {
nodes.value = String(nodes.value)
}
nodes = [new Declaration(nodes)]
} else if (nodes.selector || nodes.selectors) {
nodes = [new Rule(nodes)]
} else if (nodes.name) {
nodes = [new AtRule(nodes)]
} else if (nodes.text) {
nodes = [new Comment(nodes)]
} else {
throw new Error('Unknown node type in node creation')
}
let processed = nodes.map(i => {
/* c8 ignore next */
if (!i[my]) Container.rebuild(i)
i = i.proxyOf
if (i.parent) i.parent.removeChild(i)
if (i[isClean]) markTreeDirty(i)
if (!i.raws) i.raws = {}
if (typeof i.raws.before === 'undefined') {
if (sample && typeof sample.raws.before !== 'undefined') {
i.raws.before = sample.raws.before.replace(/\S/g, '')
}
}
i.parent = this.proxyOf
return i
})
return processed
}
prepend(...children) {
children = children.reverse()
for (let child of children) {
let nodes = this.normalize(child, this.first, 'prepend').reverse()
for (let node of nodes) this.proxyOf.nodes.unshift(node)
for (let id in this.indexes) {
this.indexes[id] = this.indexes[id] + nodes.length
}
}
this.markDirty()
return this
}
push(child) {
child.parent = this
this.proxyOf.nodes.push(child)
return this
}
removeAll() {
for (let node of this.proxyOf.nodes) node.parent = undefined
this.proxyOf.nodes = []
this.markDirty()
return this
}
removeChild(child) {
child = this.index(child)
this.proxyOf.nodes[child].parent = undefined
this.proxyOf.nodes.splice(child, 1)
let index
for (let id in this.indexes) {
index = this.indexes[id]
if (index >= child) {
this.indexes[id] = index - 1
}
}
this.markDirty()
return this
}
replaceValues(pattern, opts, callback) {
if (!callback) {
callback = opts
opts = {}
}
this.walkDecls(decl => {
if (opts.props && !opts.props.includes(decl.prop)) return
if (opts.fast && !decl.value.includes(opts.fast)) return
decl.value = decl.value.replace(pattern, callback)
})
this.markDirty()
return this
}
some(condition) {
return this.nodes.some(condition)
}
walk(callback) {
return this.each((child, i) => {
let result
try {
result = callback(child, i)
} catch (e) {
throw child.addToError(e)
}
if (result !== false && child.walk) {
result = child.walk(callback)
}
return result
})
}
walkAtRules(name, callback) {
if (!callback) {
callback = name
return this.walk((child, i) => {
if (child.type === 'atrule') {
return callback(child, i)
}
})
}
if (name instanceof RegExp) {
return this.walk((child, i) => {
if (child.type === 'atrule' && name.test(child.name)) {
return callback(child, i)
}
})
}
return this.walk((child, i) => {
if (child.type === 'atrule' && child.name === name) {
return callback(child, i)
}
})
}
walkComments(callback) {
return this.walk((child, i) => {
if (child.type === 'comment') {
return callback(child, i)
}
})
}
walkDecls(prop, callback) {
if (!callback) {
callback = prop
return this.walk((child, i) => {
if (child.type === 'decl') {
return callback(child, i)
}
})
}
if (prop instanceof RegExp) {
return this.walk((child, i) => {
if (child.type === 'decl' && prop.test(child.prop)) {
return callback(child, i)
}
})
}
return this.walk((child, i) => {
if (child.type === 'decl' && child.prop === prop) {
return callback(child, i)
}
})
}
walkRules(selector, callback) {
if (!callback) {
callback = selector
return this.walk((child, i) => {
if (child.type === 'rule') {
return callback(child, i)
}
})
}
if (selector instanceof RegExp) {
return this.walk((child, i) => {
if (child.type === 'rule' && selector.test(child.selector)) {
return callback(child, i)
}
})
}
return this.walk((child, i) => {
if (child.type === 'rule' && child.selector === selector) {
return callback(child, i)
}
})
}
}
Container.registerParse = dependant => {
parse = dependant
}
Container.registerRule = dependant => {
Rule = dependant
}
Container.registerAtRule = dependant => {
AtRule = dependant
}
Container.registerRoot = dependant => {
Root = dependant
}
module.exports = Container
Container.default = Container
/* c8 ignore start */
Container.rebuild = node => {
if (node.type === 'atrule') {
Object.setPrototypeOf(node, AtRule.prototype)
} else if (node.type === 'rule') {
Object.setPrototypeOf(node, Rule.prototype)
} else if (node.type === 'decl') {
Object.setPrototypeOf(node, Declaration.prototype)
} else if (node.type === 'comment') {
Object.setPrototypeOf(node, Comment.prototype)
} else if (node.type === 'root') {
Object.setPrototypeOf(node, Root.prototype)
}
node[my] = true
if (node.nodes) {
node.nodes.forEach(child => {
Container.rebuild(child)
})
}
}
/* c8 ignore stop */
/***/ }),
/***/ 1087:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
/**
* Copyright 2013-2015, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule isEventSupported
*/
var ExecutionEnvironment = __webpack_require__(8202);
var useHasFeature;
if (ExecutionEnvironment.canUseDOM) {
useHasFeature =
document.implementation &&
document.implementation.hasFeature &&
// always returns true in newer browsers as per the standard.
// @see http://dom.spec.whatwg.org/#dom-domimplementation-hasfeature
document.implementation.hasFeature('', '') !== true;
}
/**
* Checks if an event is supported in the current execution environment.
*
* NOTE: This will not work correctly for non-generic events such as `change`,
* `reset`, `load`, `error`, and `select`.
*
* Borrows from Modernizr.
*
* @param {string} eventNameSuffix Event name, e.g. "click".
* @param {?boolean} capture Check if the capture phase is supported.
* @return {boolean} True if the event is supported.
* @internal
* @license Modernizr 3.0.0pre (Custom Build) | MIT
*/
function isEventSupported(eventNameSuffix, capture) {
if (!ExecutionEnvironment.canUseDOM ||
capture && !('addEventListener' in document)) {
return false;
}
var eventName = 'on' + eventNameSuffix;
var isSupported = eventName in document;
if (!isSupported) {
var element = document.createElement('div');
element.setAttribute(eventName, 'return;');
isSupported = typeof element[eventName] === 'function';
}
if (!isSupported && useHasFeature && eventNameSuffix === 'wheel') {
// This is the only way to test support for the `wheel` event in IE9+.
isSupported = document.implementation.hasFeature('Events.wheel', '3.0');
}
return isSupported;
}
module.exports = isEventSupported;
/***/ }),
/***/ 1326:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
let Container = __webpack_require__(683)
class AtRule extends Container {
constructor(defaults) {
super(defaults)
this.type = 'atrule'
}
append(...children) {
if (!this.proxyOf.nodes) this.nodes = []
return super.append(...children)
}
prepend(...children) {
if (!this.proxyOf.nodes) this.nodes = []
return super.prepend(...children)
}
}
module.exports = AtRule
AtRule.default = AtRule
Container.registerAtRule(AtRule)
/***/ }),
/***/ 1381:
/***/ ((module) => {
"use strict";
module.exports.isClean = Symbol('isClean')
module.exports.my = Symbol('my')
/***/ }),
/***/ 1443:
/***/ ((module) => {
module.exports = function postcssPrefixSelector(options) {
const prefix = options.prefix;
const prefixWithSpace = /\s+$/.test(prefix) ? prefix : `${prefix} `;
const ignoreFiles = options.ignoreFiles ? [].concat(options.ignoreFiles) : [];
const includeFiles = options.includeFiles
? [].concat(options.includeFiles)
: [];
return function (root) {
if (
ignoreFiles.length &&
root.source.input.file &&
isFileInArray(root.source.input.file, ignoreFiles)
) {
return;
}
if (
includeFiles.length &&
root.source.input.file &&
!isFileInArray(root.source.input.file, includeFiles)
) {
return;
}
root.walkRules((rule) => {
const keyframeRules = [
'keyframes',
'-webkit-keyframes',
'-moz-keyframes',
'-o-keyframes',
'-ms-keyframes',
];
if (rule.parent && keyframeRules.includes(rule.parent.name)) {
return;
}
rule.selectors = rule.selectors.map((selector) => {
if (options.exclude && excludeSelector(selector, options.exclude)) {
return selector;
}
if (options.transform) {
return options.transform(
prefix,
selector,
prefixWithSpace + selector,
root.source.input.file,
rule
);
}
return prefixWithSpace + selector;
});
});
};
};
function isFileInArray(file, arr) {
return arr.some((ruleOrString) => {
if (ruleOrString instanceof RegExp) {
return ruleOrString.test(file);
}
return file.includes(ruleOrString);
});
}
function excludeSelector(selector, excludeArr) {
return excludeArr.some((excludeRule) => {
if (excludeRule instanceof RegExp) {
return excludeRule.test(selector);
}
return selector === excludeRule;
});
}
/***/ }),
/***/ 1516:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
let Node = __webpack_require__(7490)
class Declaration extends Node {
get variable() {
return this.prop.startsWith('--') || this.prop[0] === '$'
}
constructor(defaults) {
if (
defaults &&
typeof defaults.value !== 'undefined' &&
typeof defaults.value !== 'string'
) {
defaults = { ...defaults, value: String(defaults.value) }
}
super(defaults)
this.type = 'decl'
}
}
module.exports = Declaration
Declaration.default = Declaration
/***/ }),
/***/ 1524:
/***/ ((module) => {
var minus = "-".charCodeAt(0);
var plus = "+".charCodeAt(0);
var dot = ".".charCodeAt(0);
var exp = "e".charCodeAt(0);
var EXP = "E".charCodeAt(0);
// Check if three code points would start a number
// https://www.w3.org/TR/css-syntax-3/#starts-with-a-number
function likeNumber(value) {
var code = value.charCodeAt(0);
var nextCode;
if (code === plus || code === minus) {
nextCode = value.charCodeAt(1);
if (nextCode >= 48 && nextCode <= 57) {
return true;
}
var nextNextCode = value.charCodeAt(2);
if (nextCode === dot && nextNextCode >= 48 && nextNextCode <= 57) {
return true;
}
return false;
}
if (code === dot) {
nextCode = value.charCodeAt(1);
if (nextCode >= 48 && nextCode <= 57) {
return true;
}
return false;
}
if (code >= 48 && code <= 57) {
return true;
}
return false;
}
// Consume a number
// https://www.w3.org/TR/css-syntax-3/#consume-number
module.exports = function(value) {
var pos = 0;
var length = value.length;
var code;
var nextCode;
var nextNextCode;
if (length === 0 || !likeNumber(value)) {
return false;
}
code = value.charCodeAt(pos);
if (code === plus || code === minus) {
pos++;
}
while (pos < length) {
code = value.charCodeAt(pos);
if (code < 48 || code > 57) {
break;
}
pos += 1;
}
code = value.charCodeAt(pos);
nextCode = value.charCodeAt(pos + 1);
if (code === dot && nextCode >= 48 && nextCode <= 57) {
pos += 2;
while (pos < length) {
code = value.charCodeAt(pos);
if (code < 48 || code > 57) {
break;
}
pos += 1;
}
}
code = value.charCodeAt(pos);
nextCode = value.charCodeAt(pos + 1);
nextNextCode = value.charCodeAt(pos + 2);
if (
(code === exp || code === EXP) &&
((nextCode >= 48 && nextCode <= 57) ||
((nextCode === plus || nextCode === minus) &&
nextNextCode >= 48 &&
nextNextCode <= 57))
) {
pos += nextCode === plus || nextCode === minus ? 3 : 2;
while (pos < length) {
code = value.charCodeAt(pos);
if (code < 48 || code > 57) {
break;
}
pos += 1;
}
}
return {
number: value.slice(0, pos),
unit: value.slice(pos)
};
};
/***/ }),
/***/ 1544:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
var parse = __webpack_require__(8491);
var walk = __webpack_require__(3815);
var stringify = __webpack_require__(4725);
function ValueParser(value) {
if (this instanceof ValueParser) {
this.nodes = parse(value);
return this;
}
return new ValueParser(value);
}
ValueParser.prototype.toString = function() {
return Array.isArray(this.nodes) ? stringify(this.nodes) : "";
};
ValueParser.prototype.walk = function(cb, bubble) {
walk(this.nodes, cb, bubble);
return this;
};
ValueParser.unit = __webpack_require__(1524);
ValueParser.walk = walk;
ValueParser.stringify = stringify;
module.exports = ValueParser;
/***/ }),
/***/ 1609:
/***/ ((module) => {
"use strict";
module.exports = window["React"];
/***/ }),
/***/ 1670:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
let { dirname, relative, resolve, sep } = __webpack_require__(197)
let { SourceMapConsumer, SourceMapGenerator } = __webpack_require__(1866)
let { pathToFileURL } = __webpack_require__(2739)
let Input = __webpack_require__(5380)
let sourceMapAvailable = Boolean(SourceMapConsumer && SourceMapGenerator)
let pathAvailable = Boolean(dirname && resolve && relative && sep)
class MapGenerator {
constructor(stringify, root, opts, cssString) {
this.stringify = stringify
this.mapOpts = opts.map || {}
this.root = root
this.opts = opts
this.css = cssString
this.originalCSS = cssString
this.usesFileUrls = !this.mapOpts.from && this.mapOpts.absolute
this.memoizedFileURLs = new Map()
this.memoizedPaths = new Map()
this.memoizedURLs = new Map()
}
addAnnotation() {
let content
if (this.isInline()) {
content =
'data:application/json;base64,' + this.toBase64(this.map.toString())
} else if (typeof this.mapOpts.annotation === 'string') {
content = this.mapOpts.annotation
} else if (typeof this.mapOpts.annotation === 'function') {
content = this.mapOpts.annotation(this.opts.to, this.root)
} else {
content = this.outputFile() + '.map'
}
let eol = '\n'
if (this.css.includes('\r\n')) eol = '\r\n'
this.css += eol + '/*# sourceMappingURL=' + content + ' */'
}
applyPrevMaps() {
for (let prev of this.previous()) {
let from = this.toUrl(this.path(prev.file))
let root = prev.root || dirname(prev.file)
let map
if (this.mapOpts.sourcesContent === false) {
map = new SourceMapConsumer(prev.text)
if (map.sourcesContent) {
map.sourcesContent = null
}
} else {
map = prev.consumer()
}
this.map.applySourceMap(map, from, this.toUrl(this.path(root)))
}
}
clearAnnotation() {
if (this.mapOpts.annotation === false) return
if (this.root) {
let node
for (let i = this.root.nodes.length - 1; i >= 0; i--) {
node = this.root.nodes[i]
if (node.type !== 'comment') continue
if (node.text.startsWith('# sourceMappingURL=')) {
this.root.removeChild(i)
}
}
} else if (this.css) {
this.css = this.css.replace(/\n*\/\*#[\S\s]*?\*\/$/gm, '')
}
}
generate() {
this.clearAnnotation()
if (pathAvailable && sourceMapAvailable && this.isMap()) {
return this.generateMap()
} else {
let result = ''
this.stringify(this.root, i => {
result += i
})
return [result]
}
}
generateMap() {
if (this.root) {
this.generateString()
} else if (this.previous().length === 1) {
let prev = this.previous()[0].consumer()
prev.file = this.outputFile()
this.map = SourceMapGenerator.fromSourceMap(prev, {
ignoreInvalidMapping: true
})
} else {
this.map = new SourceMapGenerator({
file: this.outputFile(),
ignoreInvalidMapping: true
})
this.map.addMapping({
generated: { column: 0, line: 1 },
original: { column: 0, line: 1 },
source: this.opts.from
? this.toUrl(this.path(this.opts.from))
: '<no source>'
})
}
if (this.isSourcesContent()) this.setSourcesContent()
if (this.root && this.previous().length > 0) this.applyPrevMaps()
if (this.isAnnotation()) this.addAnnotation()
if (this.isInline()) {
return [this.css]
} else {
return [this.css, this.map]
}
}
generateString() {
this.css = ''
this.map = new SourceMapGenerator({
file: this.outputFile(),
ignoreInvalidMapping: true
})
let line = 1
let column = 1
let noSource = '<no source>'
let mapping = {
generated: { column: 0, line: 0 },
original: { column: 0, line: 0 },
source: ''
}
let last, lines
this.stringify(this.root, (str, node, type) => {
this.css += str
if (node && type !== 'end') {
mapping.generated.line = line
mapping.generated.column = column - 1
if (node.source && node.source.start) {
mapping.source = this.sourcePath(node)
mapping.original.line = node.source.start.line
mapping.original.column = node.source.start.column - 1
this.map.addMapping(mapping)
} else {
mapping.source = noSource
mapping.original.line = 1
mapping.original.column = 0
this.map.addMapping(mapping)
}
}
lines = str.match(/\n/g)
if (lines) {
line += lines.length
last = str.lastIndexOf('\n')
column = str.length - last
} else {
column += str.length
}
if (node && type !== 'start') {
let p = node.parent || { raws: {} }
let childless =
node.type === 'decl' || (node.type === 'atrule' && !node.nodes)
if (!childless || node !== p.last || p.raws.semicolon) {
if (node.source && node.source.end) {
mapping.source = this.sourcePath(node)
mapping.original.line = node.source.end.line
mapping.original.column = node.source.end.column - 1
mapping.generated.line = line
mapping.generated.column = column - 2
this.map.addMapping(mapping)
} else {
mapping.source = noSource
mapping.original.line = 1
mapping.original.column = 0
mapping.generated.line = line
mapping.generated.column = column - 1
this.map.addMapping(mapping)
}
}
}
})
}
isAnnotation() {
if (this.isInline()) {
return true
}
if (typeof this.mapOpts.annotation !== 'undefined') {
return this.mapOpts.annotation
}
if (this.previous().length) {
return this.previous().some(i => i.annotation)
}
return true
}
isInline() {
if (typeof this.mapOpts.inline !== 'undefined') {
return this.mapOpts.inline
}
let annotation = this.mapOpts.annotation
if (typeof annotation !== 'undefined' && annotation !== true) {
return false
}
if (this.previous().length) {
return this.previous().some(i => i.inline)
}
return true
}
isMap() {
if (typeof this.opts.map !== 'undefined') {
return !!this.opts.map
}
return this.previous().length > 0
}
isSourcesContent() {
if (typeof this.mapOpts.sourcesContent !== 'undefined') {
return this.mapOpts.sourcesContent
}
if (this.previous().length) {
return this.previous().some(i => i.withContent())
}
return true
}
outputFile() {
if (this.opts.to) {
return this.path(this.opts.to)
} else if (this.opts.from) {
return this.path(this.opts.from)
} else {
return 'to.css'
}
}
path(file) {
if (this.mapOpts.absolute) return file
if (file.charCodeAt(0) === 60 /* `<` */) return file
if (/^\w+:\/\//.test(file)) return file
let cached = this.memoizedPaths.get(file)
if (cached) return cached
let from = this.opts.to ? dirname(this.opts.to) : '.'
if (typeof this.mapOpts.annotation === 'string') {
from = dirname(resolve(from, this.mapOpts.annotation))
}
let path = relative(from, file)
this.memoizedPaths.set(file, path)
return path
}
previous() {
if (!this.previousMaps) {
this.previousMaps = []
if (this.root) {
this.root.walk(node => {
if (node.source && node.source.input.map) {
let map = node.source.input.map
if (!this.previousMaps.includes(map)) {
this.previousMaps.push(map)
}
}
})
} else {
let input = new Input(this.originalCSS, this.opts)
if (input.map) this.previousMaps.push(input.map)
}
}
return this.previousMaps
}
setSourcesContent() {
let already = {}
if (this.root) {
this.root.walk(node => {
if (node.source) {
let from = node.source.input.from
if (from && !already[from]) {
already[from] = true
let fromUrl = this.usesFileUrls
? this.toFileUrl(from)
: this.toUrl(this.path(from))
this.map.setSourceContent(fromUrl, node.source.input.css)
}
}
})
} else if (this.css) {
let from = this.opts.from
? this.toUrl(this.path(this.opts.from))
: '<no source>'
this.map.setSourceContent(from, this.css)
}
}
sourcePath(node) {
if (this.mapOpts.from) {
return this.toUrl(this.mapOpts.from)
} else if (this.usesFileUrls) {
return this.toFileUrl(node.source.input.from)
} else {
return this.toUrl(this.path(node.source.input.from))
}
}
toBase64(str) {
if (Buffer) {
return Buffer.from(str).toString('base64')
} else {
return window.btoa(unescape(encodeURIComponent(str)))
}
}
toFileUrl(path) {
let cached = this.memoizedFileURLs.get(path)
if (cached) return cached
if (pathToFileURL) {
let fileURL = pathToFileURL(path).toString()
this.memoizedFileURLs.set(path, fileURL)
return fileURL
} else {
throw new Error(
'`map.absolute` option is not available in this PostCSS build'
)
}
}
toUrl(path) {
let cached = this.memoizedURLs.get(path)
if (cached) return cached
if (sep === '\\') {
path = path.replace(/\\/g, '/')
}
let url = encodeURI(path).replace(/[#?]/g, encodeURIComponent)
this.memoizedURLs.set(path, url)
return url
}
}
module.exports = MapGenerator
/***/ }),
/***/ 1866:
/***/ (() => {
/* (ignored) */
/***/ }),
/***/ 2213:
/***/ ((module) => {
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* @providesModule UserAgent_DEPRECATED
*/
/**
* Provides entirely client-side User Agent and OS detection. You should prefer
* the non-deprecated UserAgent module when possible, which exposes our
* authoritative server-side PHP-based detection to the client.
*
* Usage is straightforward:
*
* if (UserAgent_DEPRECATED.ie()) {
* // IE
* }
*
* You can also do version checks:
*
* if (UserAgent_DEPRECATED.ie() >= 7) {
* // IE7 or better
* }
*
* The browser functions will return NaN if the browser does not match, so
* you can also do version compares the other way:
*
* if (UserAgent_DEPRECATED.ie() < 7) {
* // IE6 or worse
* }
*
* Note that the version is a float and may include a minor version number,
* so you should always use range operators to perform comparisons, not
* strict equality.
*
* **Note:** You should **strongly** prefer capability detection to browser
* version detection where it's reasonable:
*
* http://www.quirksmode.org/js/support.html
*
* Further, we have a large number of mature wrapper functions and classes
* which abstract away many browser irregularities. Check the documentation,
* grep for things, or ask on javascript@lists.facebook.com before writing yet
* another copy of "event || window.event".
*
*/
var _populated = false;
// Browsers
var _ie, _firefox, _opera, _webkit, _chrome;
// Actual IE browser for compatibility mode
var _ie_real_version;
// Platforms
var _osx, _windows, _linux, _android;
// Architectures
var _win64;
// Devices
var _iphone, _ipad, _native;
var _mobile;
function _populate() {
if (_populated) {
return;
}
_populated = true;
// To work around buggy JS libraries that can't handle multi-digit
// version numbers, Opera 10's user agent string claims it's Opera
// 9, then later includes a Version/X.Y field:
//
// Opera/9.80 (foo) Presto/2.2.15 Version/10.10
var uas = navigator.userAgent;
var agent = /(?:MSIE.(\d+\.\d+))|(?:(?:Firefox|GranParadiso|Iceweasel).(\d+\.\d+))|(?:Opera(?:.+Version.|.)(\d+\.\d+))|(?:AppleWebKit.(\d+(?:\.\d+)?))|(?:Trident\/\d+\.\d+.*rv:(\d+\.\d+))/.exec(uas);
var os = /(Mac OS X)|(Windows)|(Linux)/.exec(uas);
_iphone = /\b(iPhone|iP[ao]d)/.exec(uas);
_ipad = /\b(iP[ao]d)/.exec(uas);
_android = /Android/i.exec(uas);
_native = /FBAN\/\w+;/i.exec(uas);
_mobile = /Mobile/i.exec(uas);
// Note that the IE team blog would have you believe you should be checking
// for 'Win64; x64'. But MSDN then reveals that you can actually be coming
// from either x64 or ia64; so ultimately, you should just check for Win64
// as in indicator of whether you're in 64-bit IE. 32-bit IE on 64-bit
// Windows will send 'WOW64' instead.
_win64 = !!(/Win64/.exec(uas));
if (agent) {
_ie = agent[1] ? parseFloat(agent[1]) : (
agent[5] ? parseFloat(agent[5]) : NaN);
// IE compatibility mode
if (_ie && document && document.documentMode) {
_ie = document.documentMode;
}
// grab the "true" ie version from the trident token if available
var trident = /(?:Trident\/(\d+.\d+))/.exec(uas);
_ie_real_version = trident ? parseFloat(trident[1]) + 4 : _ie;
_firefox = agent[2] ? parseFloat(agent[2]) : NaN;
_opera = agent[3] ? parseFloat(agent[3]) : NaN;
_webkit = agent[4] ? parseFloat(agent[4]) : NaN;
if (_webkit) {
// We do not add the regexp to the above test, because it will always
// match 'safari' only since 'AppleWebKit' appears before 'Chrome' in
// the userAgent string.
agent = /(?:Chrome\/(\d+\.\d+))/.exec(uas);
_chrome = agent && agent[1] ? parseFloat(agent[1]) : NaN;
} else {
_chrome = NaN;
}
} else {
_ie = _firefox = _opera = _chrome = _webkit = NaN;
}
if (os) {
if (os[1]) {
// Detect OS X version. If no version number matches, set _osx to true.
// Version examples: 10, 10_6_1, 10.7
// Parses version number as a float, taking only first two sets of
// digits. If only one set of digits is found, returns just the major
// version number.
var ver = /(?:Mac OS X (\d+(?:[._]\d+)?))/.exec(uas);
_osx = ver ? parseFloat(ver[1].replace('_', '.')) : true;
} else {
_osx = false;
}
_windows = !!os[2];
_linux = !!os[3];
} else {
_osx = _windows = _linux = false;
}
}
var UserAgent_DEPRECATED = {
/**
* Check if the UA is Internet Explorer.
*
*
* @return float|NaN Version number (if match) or NaN.
*/
ie: function() {
return _populate() || _ie;
},
/**
* Check if we're in Internet Explorer compatibility mode.
*
* @return bool true if in compatibility mode, false if
* not compatibility mode or not ie
*/
ieCompatibilityMode: function() {
return _populate() || (_ie_real_version > _ie);
},
/**
* Whether the browser is 64-bit IE. Really, this is kind of weak sauce; we
* only need this because Skype can't handle 64-bit IE yet. We need to remove
* this when we don't need it -- tracked by #601957.
*/
ie64: function() {
return UserAgent_DEPRECATED.ie() && _win64;
},
/**
* Check if the UA is Firefox.
*
*
* @return float|NaN Version number (if match) or NaN.
*/
firefox: function() {
return _populate() || _firefox;
},
/**
* Check if the UA is Opera.
*
*
* @return float|NaN Version number (if match) or NaN.
*/
opera: function() {
return _populate() || _opera;
},
/**
* Check if the UA is WebKit.
*
*
* @return float|NaN Version number (if match) or NaN.
*/
webkit: function() {
return _populate() || _webkit;
},
/**
* For Push
* WILL BE REMOVED VERY SOON. Use UserAgent_DEPRECATED.webkit
*/
safari: function() {
return UserAgent_DEPRECATED.webkit();
},
/**
* Check if the UA is a Chrome browser.
*
*
* @return float|NaN Version number (if match) or NaN.
*/
chrome : function() {
return _populate() || _chrome;
},
/**
* Check if the user is running Windows.
*
* @return bool `true' if the user's OS is Windows.
*/
windows: function() {
return _populate() || _windows;
},
/**
* Check if the user is running Mac OS X.
*
* @return float|bool Returns a float if a version number is detected,
* otherwise true/false.
*/
osx: function() {
return _populate() || _osx;
},
/**
* Check if the user is running Linux.
*
* @return bool `true' if the user's OS is some flavor of Linux.
*/
linux: function() {
return _populate() || _linux;
},
/**
* Check if the user is running on an iPhone or iPod platform.
*
* @return bool `true' if the user is running some flavor of the
* iPhone OS.
*/
iphone: function() {
return _populate() || _iphone;
},
mobile: function() {
return _populate() || (_iphone || _ipad || _android || _mobile);
},
nativeApp: function() {
// webviews inside of the native apps
return _populate() || _native;
},
android: function() {
return _populate() || _android;
},
ipad: function() {
return _populate() || _ipad;
}
};
module.exports = UserAgent_DEPRECATED;
/***/ }),
/***/ 2327:
/***/ ((module) => {
"use strict";
const SINGLE_QUOTE = "'".charCodeAt(0)
const DOUBLE_QUOTE = '"'.charCodeAt(0)
const BACKSLASH = '\\'.charCodeAt(0)
const SLASH = '/'.charCodeAt(0)
const NEWLINE = '\n'.charCodeAt(0)
const SPACE = ' '.charCodeAt(0)
const FEED = '\f'.charCodeAt(0)
const TAB = '\t'.charCodeAt(0)
const CR = '\r'.charCodeAt(0)
const OPEN_SQUARE = '['.charCodeAt(0)
const CLOSE_SQUARE = ']'.charCodeAt(0)
const OPEN_PARENTHESES = '('.charCodeAt(0)
const CLOSE_PARENTHESES = ')'.charCodeAt(0)
const OPEN_CURLY = '{'.charCodeAt(0)
const CLOSE_CURLY = '}'.charCodeAt(0)
const SEMICOLON = ';'.charCodeAt(0)
const ASTERISK = '*'.charCodeAt(0)
const COLON = ':'.charCodeAt(0)
const AT = '@'.charCodeAt(0)
const RE_AT_END = /[\t\n\f\r "#'()/;[\\\]{}]/g
const RE_WORD_END = /[\t\n\f\r !"#'():;@[\\\]{}]|\/(?=\*)/g
const RE_BAD_BRACKET = /.[\r\n"'(/\\]/
const RE_HEX_ESCAPE = /[\da-f]/i
module.exports = function tokenizer(input, options = {}) {
let css = input.css.valueOf()
let ignore = options.ignoreErrors
let code, content, escape, next, quote
let currentToken, escaped, escapePos, n, prev
let length = css.length
let pos = 0
let buffer = []
let returned = []
function position() {
return pos
}
function unclosed(what) {
throw input.error('Unclosed ' + what, pos)
}
function endOfFile() {
return returned.length === 0 && pos >= length
}
function nextToken(opts) {
if (returned.length) return returned.pop()
if (pos >= length) return
let ignoreUnclosed = opts ? opts.ignoreUnclosed : false
code = css.charCodeAt(pos)
switch (code) {
case NEWLINE:
case SPACE:
case TAB:
case CR:
case FEED: {
next = pos
do {
next += 1
code = css.charCodeAt(next)
} while (
code === SPACE ||
code === NEWLINE ||
code === TAB ||
code === CR ||
code === FEED
)
currentToken = ['space', css.slice(pos, next)]
pos = next - 1
break
}
case OPEN_SQUARE:
case CLOSE_SQUARE:
case OPEN_CURLY:
case CLOSE_CURLY:
case COLON:
case SEMICOLON:
case CLOSE_PARENTHESES: {
let controlChar = String.fromCharCode(code)
currentToken = [controlChar, controlChar, pos]
break
}
case OPEN_PARENTHESES: {
prev = buffer.length ? buffer.pop()[1] : ''
n = css.charCodeAt(pos + 1)
if (
prev === 'url' &&
n !== SINGLE_QUOTE &&
n !== DOUBLE_QUOTE &&
n !== SPACE &&
n !== NEWLINE &&
n !== TAB &&
n !== FEED &&
n !== CR
) {
next = pos
do {
escaped = false
next = css.indexOf(')', next + 1)
if (next === -1) {
if (ignore || ignoreUnclosed) {
next = pos
break
} else {
unclosed('bracket')
}
}
escapePos = next
while (css.charCodeAt(escapePos - 1) === BACKSLASH) {
escapePos -= 1
escaped = !escaped
}
} while (escaped)
currentToken = ['brackets', css.slice(pos, next + 1), pos, next]
pos = next
} else {
next = css.indexOf(')', pos + 1)
content = css.slice(pos, next + 1)
if (next === -1 || RE_BAD_BRACKET.test(content)) {
currentToken = ['(', '(', pos]
} else {
currentToken = ['brackets', content, pos, next]
pos = next
}
}
break
}
case SINGLE_QUOTE:
case DOUBLE_QUOTE: {
quote = code === SINGLE_QUOTE ? "'" : '"'
next = pos
do {
escaped = false
next = css.indexOf(quote, next + 1)
if (next === -1) {
if (ignore || ignoreUnclosed) {
next = pos + 1
break
} else {
unclosed('string')
}
}
escapePos = next
while (css.charCodeAt(escapePos - 1) === BACKSLASH) {
escapePos -= 1
escaped = !escaped
}
} while (escaped)
currentToken = ['string', css.slice(pos, next + 1), pos, next]
pos = next
break
}
case AT: {
RE_AT_END.lastIndex = pos + 1
RE_AT_END.test(css)
if (RE_AT_END.lastIndex === 0) {
next = css.length - 1
} else {
next = RE_AT_END.lastIndex - 2
}
currentToken = ['at-word', css.slice(pos, next + 1), pos, next]
pos = next
break
}
case BACKSLASH: {
next = pos
escape = true
while (css.charCodeAt(next + 1) === BACKSLASH) {
next += 1
escape = !escape
}
code = css.charCodeAt(next + 1)
if (
escape &&
code !== SLASH &&
code !== SPACE &&
code !== NEWLINE &&
code !== TAB &&
code !== CR &&
code !== FEED
) {
next += 1
if (RE_HEX_ESCAPE.test(css.charAt(next))) {
while (RE_HEX_ESCAPE.test(css.charAt(next + 1))) {
next += 1
}
if (css.charCodeAt(next + 1) === SPACE) {
next += 1
}
}
}
currentToken = ['word', css.slice(pos, next + 1), pos, next]
pos = next
break
}
default: {
if (code === SLASH && css.charCodeAt(pos + 1) === ASTERISK) {
next = css.indexOf('*/', pos + 2) + 1
if (next === 0) {
if (ignore || ignoreUnclosed) {
next = css.length
} else {
unclosed('comment')
}
}
currentToken = ['comment', css.slice(pos, next + 1), pos, next]
pos = next
} else {
RE_WORD_END.lastIndex = pos + 1
RE_WORD_END.test(css)
if (RE_WORD_END.lastIndex === 0) {
next = css.length - 1
} else {
next = RE_WORD_END.lastIndex - 2
}
currentToken = ['word', css.slice(pos, next + 1), pos, next]
buffer.push(currentToken)
pos = next
}
break
}
}
pos++
return currentToken
}
function back(token) {
returned.push(token)
}
return {
back,
endOfFile,
nextToken,
position
}
}
/***/ }),
/***/ 2739:
/***/ (() => {
/* (ignored) */
/***/ }),
/***/ 2775:
/***/ ((module) => {
var x=String;
var create=function() {return {isColorSupported:false,reset:x,bold:x,dim:x,italic:x,underline:x,inverse:x,hidden:x,strikethrough:x,black:x,red:x,green:x,yellow:x,blue:x,magenta:x,cyan:x,white:x,gray:x,bgBlack:x,bgRed:x,bgGreen:x,bgYellow:x,bgBlue:x,bgMagenta:x,bgCyan:x,bgWhite:x,blackBright:x,redBright:x,greenBright:x,yellowBright:x,blueBright:x,magentaBright:x,cyanBright:x,whiteBright:x,bgBlackBright:x,bgRedBright:x,bgGreenBright:x,bgYellowBright:x,bgBlueBright:x,bgMagentaBright:x,bgCyanBright:x,bgWhiteBright:x}};
module.exports=create();
module.exports.createColors = create;
/***/ }),
/***/ 3122:
/***/ ((module) => {
"use strict";
/* eslint-disable no-console */
let printed = {}
module.exports = function warnOnce(message) {
if (printed[message]) return
printed[message] = true
if (typeof console !== 'undefined' && console.warn) {
console.warn(message)
}
}
/***/ }),
/***/ 3815:
/***/ ((module) => {
module.exports = function walk(nodes, cb, bubble) {
var i, max, node, result;
for (i = 0, max = nodes.length; i < max; i += 1) {
node = nodes[i];
if (!bubble) {
result = cb(node, i, nodes);
}
if (
result !== false &&
node.type === "function" &&
Array.isArray(node.nodes)
) {
walk(node.nodes, cb, bubble);
}
if (bubble) {
cb(node, i, nodes);
}
}
};
/***/ }),
/***/ 3937:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
let AtRule = __webpack_require__(1326)
let Comment = __webpack_require__(6589)
let Declaration = __webpack_require__(1516)
let Root = __webpack_require__(9434)
let Rule = __webpack_require__(4092)
let tokenizer = __webpack_require__(2327)
const SAFE_COMMENT_NEIGHBOR = {
empty: true,
space: true
}
function findLastWithPosition(tokens) {
for (let i = tokens.length - 1; i >= 0; i--) {
let token = tokens[i]
let pos = token[3] || token[2]
if (pos) return pos
}
}
class Parser {
constructor(input) {
this.input = input
this.root = new Root()
this.current = this.root
this.spaces = ''
this.semicolon = false
this.createTokenizer()
this.root.source = { input, start: { column: 1, line: 1, offset: 0 } }
}
atrule(token) {
let node = new AtRule()
node.name = token[1].slice(1)
if (node.name === '') {
this.unnamedAtrule(node, token)
}
this.init(node, token[2])
let type
let prev
let shift
let last = false
let open = false
let params = []
let brackets = []
while (!this.tokenizer.endOfFile()) {
token = this.tokenizer.nextToken()
type = token[0]
if (type === '(' || type === '[') {
brackets.push(type === '(' ? ')' : ']')
} else if (type === '{' && brackets.length > 0) {
brackets.push('}')
} else if (type === brackets[brackets.length - 1]) {
brackets.pop()
}
if (brackets.length === 0) {
if (type === ';') {
node.source.end = this.getPosition(token[2])
node.source.end.offset++
this.semicolon = true
break
} else if (type === '{') {
open = true
break
} else if (type === '}') {
if (params.length > 0) {
shift = params.length - 1
prev = params[shift]
while (prev && prev[0] === 'space') {
prev = params[--shift]
}
if (prev) {
node.source.end = this.getPosition(prev[3] || prev[2])
node.source.end.offset++
}
}
this.end(token)
break
} else {
params.push(token)
}
} else {
params.push(token)
}
if (this.tokenizer.endOfFile()) {
last = true
break
}
}
node.raws.between = this.spacesAndCommentsFromEnd(params)
if (params.length) {
node.raws.afterName = this.spacesAndCommentsFromStart(params)
this.raw(node, 'params', params)
if (last) {
token = params[params.length - 1]
node.source.end = this.getPosition(token[3] || token[2])
node.source.end.offset++
this.spaces = node.raws.between
node.raws.between = ''
}
} else {
node.raws.afterName = ''
node.params = ''
}
if (open) {
node.nodes = []
this.current = node
}
}
checkMissedSemicolon(tokens) {
let colon = this.colon(tokens)
if (colon === false) return
let founded = 0
let token
for (let j = colon - 1; j >= 0; j--) {
token = tokens[j]
if (token[0] !== 'space') {
founded += 1
if (founded === 2) break
}
}
// If the token is a word, e.g. `!important`, `red` or any other valid property's value.
// Then we need to return the colon after that word token. [3] is the "end" colon of that word.
// And because we need it after that one we do +1 to get the next one.
throw this.input.error(
'Missed semicolon',
token[0] === 'word' ? token[3] + 1 : token[2]
)
}
colon(tokens) {
let brackets = 0
let prev, token, type
for (let [i, element] of tokens.entries()) {
token = element
type = token[0]
if (type === '(') {
brackets += 1
}
if (type === ')') {
brackets -= 1
}
if (brackets === 0 && type === ':') {
if (!prev) {
this.doubleColon(token)
} else if (prev[0] === 'word' && prev[1] === 'progid') {
continue
} else {
return i
}
}
prev = token
}
return false
}
comment(token) {
let node = new Comment()
this.init(node, token[2])
node.source.end = this.getPosition(token[3] || token[2])
node.source.end.offset++
let text = token[1].slice(2, -2)
if (/^\s*$/.test(text)) {
node.text = ''
node.raws.left = text
node.raws.right = ''
} else {
let match = text.match(/^(\s*)([^]*\S)(\s*)$/)
node.text = match[2]
node.raws.left = match[1]
node.raws.right = match[3]
}
}
createTokenizer() {
this.tokenizer = tokenizer(this.input)
}
decl(tokens, customProperty) {
let node = new Declaration()
this.init(node, tokens[0][2])
let last = tokens[tokens.length - 1]
if (last[0] === ';') {
this.semicolon = true
tokens.pop()
}
node.source.end = this.getPosition(
last[3] || last[2] || findLastWithPosition(tokens)
)
node.source.end.offset++
while (tokens[0][0] !== 'word') {
if (tokens.length === 1) this.unknownWord(tokens)
node.raws.before += tokens.shift()[1]
}
node.source.start = this.getPosition(tokens[0][2])
node.prop = ''
while (tokens.length) {
let type = tokens[0][0]
if (type === ':' || type === 'space' || type === 'comment') {
break
}
node.prop += tokens.shift()[1]
}
node.raws.between = ''
let token
while (tokens.length) {
token = tokens.shift()
if (token[0] === ':') {
node.raws.between += token[1]
break
} else {
if (token[0] === 'word' && /\w/.test(token[1])) {
this.unknownWord([token])
}
node.raws.between += token[1]
}
}
if (node.prop[0] === '_' || node.prop[0] === '*') {
node.raws.before += node.prop[0]
node.prop = node.prop.slice(1)
}
let firstSpaces = []
let next
while (tokens.length) {
next = tokens[0][0]
if (next !== 'space' && next !== 'comment') break
firstSpaces.push(tokens.shift())
}
this.precheckMissedSemicolon(tokens)
for (let i = tokens.length - 1; i >= 0; i--) {
token = tokens[i]
if (token[1].toLowerCase() === '!important') {
node.important = true
let string = this.stringFrom(tokens, i)
string = this.spacesFromEnd(tokens) + string
if (string !== ' !important') node.raws.important = string
break
} else if (token[1].toLowerCase() === 'important') {
let cache = tokens.slice(0)
let str = ''
for (let j = i; j > 0; j--) {
let type = cache[j][0]
if (str.trim().startsWith('!') && type !== 'space') {
break
}
str = cache.pop()[1] + str
}
if (str.trim().startsWith('!')) {
node.important = true
node.raws.important = str
tokens = cache
}
}
if (token[0] !== 'space' && token[0] !== 'comment') {
break
}
}
let hasWord = tokens.some(i => i[0] !== 'space' && i[0] !== 'comment')
if (hasWord) {
node.raws.between += firstSpaces.map(i => i[1]).join('')
firstSpaces = []
}
this.raw(node, 'value', firstSpaces.concat(tokens), customProperty)
if (node.value.includes(':') && !customProperty) {
this.checkMissedSemicolon(tokens)
}
}
doubleColon(token) {
throw this.input.error(
'Double colon',
{ offset: token[2] },
{ offset: token[2] + token[1].length }
)
}
emptyRule(token) {
let node = new Rule()
this.init(node, token[2])
node.selector = ''
node.raws.between = ''
this.current = node
}
end(token) {
if (this.current.nodes && this.current.nodes.length) {
this.current.raws.semicolon = this.semicolon
}
this.semicolon = false
this.current.raws.after = (this.current.raws.after || '') + this.spaces
this.spaces = ''
if (this.current.parent) {
this.current.source.end = this.getPosition(token[2])
this.current.source.end.offset++
this.current = this.current.parent
} else {
this.unexpectedClose(token)
}
}
endFile() {
if (this.current.parent) this.unclosedBlock()
if (this.current.nodes && this.current.nodes.length) {
this.current.raws.semicolon = this.semicolon
}
this.current.raws.after = (this.current.raws.after || '') + this.spaces
this.root.source.end = this.getPosition(this.tokenizer.position())
}
freeSemicolon(token) {
this.spaces += token[1]
if (this.current.nodes) {
let prev = this.current.nodes[this.current.nodes.length - 1]
if (prev && prev.type === 'rule' && !prev.raws.ownSemicolon) {
prev.raws.ownSemicolon = this.spaces
this.spaces = ''
prev.source.end = this.getPosition(token[2])
prev.source.end.offset += prev.raws.ownSemicolon.length
}
}
}
// Helpers
getPosition(offset) {
let pos = this.input.fromOffset(offset)
return {
column: pos.col,
line: pos.line,
offset
}
}
init(node, offset) {
this.current.push(node)
node.source = {
input: this.input,
start: this.getPosition(offset)
}
node.raws.before = this.spaces
this.spaces = ''
if (node.type !== 'comment') this.semicolon = false
}
other(start) {
let end = false
let type = null
let colon = false
let bracket = null
let brackets = []
let customProperty = start[1].startsWith('--')
let tokens = []
let token = start
while (token) {
type = token[0]
tokens.push(token)
if (type === '(' || type === '[') {
if (!bracket) bracket = token
brackets.push(type === '(' ? ')' : ']')
} else if (customProperty && colon && type === '{') {
if (!bracket) bracket = token
brackets.push('}')
} else if (brackets.length === 0) {
if (type === ';') {
if (colon) {
this.decl(tokens, customProperty)
return
} else {
break
}
} else if (type === '{') {
this.rule(tokens)
return
} else if (type === '}') {
this.tokenizer.back(tokens.pop())
end = true
break
} else if (type === ':') {
colon = true
}
} else if (type === brackets[brackets.length - 1]) {
brackets.pop()
if (brackets.length === 0) bracket = null
}
token = this.tokenizer.nextToken()
}
if (this.tokenizer.endOfFile()) end = true
if (brackets.length > 0) this.unclosedBracket(bracket)
if (end && colon) {
if (!customProperty) {
while (tokens.length) {
token = tokens[tokens.length - 1][0]
if (token !== 'space' && token !== 'comment') break
this.tokenizer.back(tokens.pop())
}
}
this.decl(tokens, customProperty)
} else {
this.unknownWord(tokens)
}
}
parse() {
let token
while (!this.tokenizer.endOfFile()) {
token = this.tokenizer.nextToken()
switch (token[0]) {
case 'space':
this.spaces += token[1]
break
case ';':
this.freeSemicolon(token)
break
case '}':
this.end(token)
break
case 'comment':
this.comment(token)
break
case 'at-word':
this.atrule(token)
break
case '{':
this.emptyRule(token)
break
default:
this.other(token)
break
}
}
this.endFile()
}
precheckMissedSemicolon(/* tokens */) {
// Hook for Safe Parser
}
raw(node, prop, tokens, customProperty) {
let token, type
let length = tokens.length
let value = ''
let clean = true
let next, prev
for (let i = 0; i < length; i += 1) {
token = tokens[i]
type = token[0]
if (type === 'space' && i === length - 1 && !customProperty) {
clean = false
} else if (type === 'comment') {
prev = tokens[i - 1] ? tokens[i - 1][0] : 'empty'
next = tokens[i + 1] ? tokens[i + 1][0] : 'empty'
if (!SAFE_COMMENT_NEIGHBOR[prev] && !SAFE_COMMENT_NEIGHBOR[next]) {
if (value.slice(-1) === ',') {
clean = false
} else {
value += token[1]
}
} else {
clean = false
}
} else {
value += token[1]
}
}
if (!clean) {
let raw = tokens.reduce((all, i) => all + i[1], '')
node.raws[prop] = { raw, value }
}
node[prop] = value
}
rule(tokens) {
tokens.pop()
let node = new Rule()
this.init(node, tokens[0][2])
node.raws.between = this.spacesAndCommentsFromEnd(tokens)
this.raw(node, 'selector', tokens)
this.current = node
}
spacesAndCommentsFromEnd(tokens) {
let lastTokenType
let spaces = ''
while (tokens.length) {
lastTokenType = tokens[tokens.length - 1][0]
if (lastTokenType !== 'space' && lastTokenType !== 'comment') break
spaces = tokens.pop()[1] + spaces
}
return spaces
}
// Errors
spacesAndCommentsFromStart(tokens) {
let next
let spaces = ''
while (tokens.length) {
next = tokens[0][0]
if (next !== 'space' && next !== 'comment') break
spaces += tokens.shift()[1]
}
return spaces
}
spacesFromEnd(tokens) {
let lastTokenType
let spaces = ''
while (tokens.length) {
lastTokenType = tokens[tokens.length - 1][0]
if (lastTokenType !== 'space') break
spaces = tokens.pop()[1] + spaces
}
return spaces
}
stringFrom(tokens, from) {
let result = ''
for (let i = from; i < tokens.length; i++) {
result += tokens[i][1]
}
tokens.splice(from, tokens.length - from)
return result
}
unclosedBlock() {
let pos = this.current.source.start
throw this.input.error('Unclosed block', pos.line, pos.column)
}
unclosedBracket(bracket) {
throw this.input.error(
'Unclosed bracket',
{ offset: bracket[2] },
{ offset: bracket[2] + 1 }
)
}
unexpectedClose(token) {
throw this.input.error(
'Unexpected }',
{ offset: token[2] },
{ offset: token[2] + 1 }
)
}
unknownWord(tokens) {
throw this.input.error(
'Unknown word ' + tokens[0][1],
{ offset: tokens[0][2] },
{ offset: tokens[0][2] + tokens[0][1].length }
)
}
unnamedAtrule(node, token) {
throw this.input.error(
'At-rule without name',
{ offset: token[2] },
{ offset: token[2] + token[1].length }
)
}
}
module.exports = Parser
/***/ }),
/***/ 4067:
/***/ ((module) => {
"use strict";
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
var ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED';
module.exports = ReactPropTypesSecret;
/***/ }),
/***/ 4092:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
let Container = __webpack_require__(683)
let list = __webpack_require__(7374)
class Rule extends Container {
get selectors() {
return list.comma(this.selector)
}
set selectors(values) {
let match = this.selector ? this.selector.match(/,\s*/) : null
let sep = match ? match[0] : ',' + this.raw('between', 'beforeOpen')
this.selector = values.join(sep)
}
constructor(defaults) {
super(defaults)
this.type = 'rule'
if (!this.nodes) this.nodes = []
}
}
module.exports = Rule
Rule.default = Rule
Container.registerRule(Rule)
/***/ }),
/***/ 4132:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
"use strict";
var __webpack_unused_export__;
__webpack_unused_export__ = true;
var TextareaAutosize_1 = __webpack_require__(4462);
exports.A = TextareaAutosize_1.TextareaAutosize;
/***/ }),
/***/ 4295:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
let Container = __webpack_require__(683)
let Input = __webpack_require__(5380)
let Parser = __webpack_require__(3937)
function parse(css, opts) {
let input = new Input(css, opts)
let parser = new Parser(input)
try {
parser.parse()
} catch (e) {
if (false) {}
throw e
}
return parser.root
}
module.exports = parse
parse.default = parse
Container.registerParse(parse)
/***/ }),
/***/ 4306:
/***/ (function(module, exports) {
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
autosize 4.0.4
license: MIT
http://www.jacklmoore.com/autosize
*/
(function (global, factory) {
if (true) {
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [module, exports], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
} else { var mod; }
})(this, function (module, exports) {
'use strict';
var map = typeof Map === "function" ? new Map() : function () {
var keys = [];
var values = [];
return {
has: function has(key) {
return keys.indexOf(key) > -1;
},
get: function get(key) {
return values[keys.indexOf(key)];
},
set: function set(key, value) {
if (keys.indexOf(key) === -1) {
keys.push(key);
values.push(value);
}
},
delete: function _delete(key) {
var index = keys.indexOf(key);
if (index > -1) {
keys.splice(index, 1);
values.splice(index, 1);
}
}
};
}();
var createEvent = function createEvent(name) {
return new Event(name, { bubbles: true });
};
try {
new Event('test');
} catch (e) {
// IE does not support `new Event()`
createEvent = function createEvent(name) {
var evt = document.createEvent('Event');
evt.initEvent(name, true, false);
return evt;
};
}
function assign(ta) {
if (!ta || !ta.nodeName || ta.nodeName !== 'TEXTAREA' || map.has(ta)) return;
var heightOffset = null;
var clientWidth = null;
var cachedHeight = null;
function init() {
var style = window.getComputedStyle(ta, null);
if (style.resize === 'vertical') {
ta.style.resize = 'none';
} else if (style.resize === 'both') {
ta.style.resize = 'horizontal';
}
if (style.boxSizing === 'content-box') {
heightOffset = -(parseFloat(style.paddingTop) + parseFloat(style.paddingBottom));
} else {
heightOffset = parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);
}
// Fix when a textarea is not on document body and heightOffset is Not a Number
if (isNaN(heightOffset)) {
heightOffset = 0;
}
update();
}
function changeOverflow(value) {
{
// Chrome/Safari-specific fix:
// When the textarea y-overflow is hidden, Chrome/Safari do not reflow the text to account for the space
// made available by removing the scrollbar. The following forces the necessary text reflow.
var width = ta.style.width;
ta.style.width = '0px';
// Force reflow:
/* jshint ignore:start */
ta.offsetWidth;
/* jshint ignore:end */
ta.style.width = width;
}
ta.style.overflowY = value;
}
function getParentOverflows(el) {
var arr = [];
while (el && el.parentNode && el.parentNode instanceof Element) {
if (el.parentNode.scrollTop) {
arr.push({
node: el.parentNode,
scrollTop: el.parentNode.scrollTop
});
}
el = el.parentNode;
}
return arr;
}
function resize() {
if (ta.scrollHeight === 0) {
// If the scrollHeight is 0, then the element probably has display:none or is detached from the DOM.
return;
}
var overflows = getParentOverflows(ta);
var docTop = document.documentElement && document.documentElement.scrollTop; // Needed for Mobile IE (ticket #240)
ta.style.height = '';
ta.style.height = ta.scrollHeight + heightOffset + 'px';
// used to check if an update is actually necessary on window.resize
clientWidth = ta.clientWidth;
// prevents scroll-position jumping
overflows.forEach(function (el) {
el.node.scrollTop = el.scrollTop;
});
if (docTop) {
document.documentElement.scrollTop = docTop;
}
}
function update() {
resize();
var styleHeight = Math.round(parseFloat(ta.style.height));
var computed = window.getComputedStyle(ta, null);
// Using offsetHeight as a replacement for computed.height in IE, because IE does not account use of border-box
var actualHeight = computed.boxSizing === 'content-box' ? Math.round(parseFloat(computed.height)) : ta.offsetHeight;
// The actual height not matching the style height (set via the resize method) indicates that
// the max-height has been exceeded, in which case the overflow should be allowed.
if (actualHeight < styleHeight) {
if (computed.overflowY === 'hidden') {
changeOverflow('scroll');
resize();
actualHeight = computed.boxSizing === 'content-box' ? Math.round(parseFloat(window.getComputedStyle(ta, null).height)) : ta.offsetHeight;
}
} else {
// Normally keep overflow set to hidden, to avoid flash of scrollbar as the textarea expands.
if (computed.overflowY !== 'hidden') {
changeOverflow('hidden');
resize();
actualHeight = computed.boxSizing === 'content-box' ? Math.round(parseFloat(window.getComputedStyle(ta, null).height)) : ta.offsetHeight;
}
}
if (cachedHeight !== actualHeight) {
cachedHeight = actualHeight;
var evt = createEvent('autosize:resized');
try {
ta.dispatchEvent(evt);
} catch (err) {
// Firefox will throw an error on dispatchEvent for a detached element
// https://bugzilla.mozilla.org/show_bug.cgi?id=889376
}
}
}
var pageResize = function pageResize() {
if (ta.clientWidth !== clientWidth) {
update();
}
};
var destroy = function (style) {
window.removeEventListener('resize', pageResize, false);
ta.removeEventListener('input', update, false);
ta.removeEventListener('keyup', update, false);
ta.removeEventListener('autosize:destroy', destroy, false);
ta.removeEventListener('autosize:update', update, false);
Object.keys(style).forEach(function (key) {
ta.style[key] = style[key];
});
map.delete(ta);
}.bind(ta, {
height: ta.style.height,
resize: ta.style.resize,
overflowY: ta.style.overflowY,
overflowX: ta.style.overflowX,
wordWrap: ta.style.wordWrap
});
ta.addEventListener('autosize:destroy', destroy, false);
// IE9 does not fire onpropertychange or oninput for deletions,
// so binding to onkeyup to catch most of those events.
// There is no way that I know of to detect something like 'cut' in IE9.
if ('onpropertychange' in ta && 'oninput' in ta) {
ta.addEventListener('keyup', update, false);
}
window.addEventListener('resize', pageResize, false);
ta.addEventListener('input', update, false);
ta.addEventListener('autosize:update', update, false);
ta.style.overflowX = 'hidden';
ta.style.wordWrap = 'break-word';
map.set(ta, {
destroy: destroy,
update: update
});
init();
}
function destroy(ta) {
var methods = map.get(ta);
if (methods) {
methods.destroy();
}
}
function update(ta) {
var methods = map.get(ta);
if (methods) {
methods.update();
}
}
var autosize = null;
// Do nothing in Node.js environment and IE8 (or lower)
if (typeof window === 'undefined' || typeof window.getComputedStyle !== 'function') {
autosize = function autosize(el) {
return el;
};
autosize.destroy = function (el) {
return el;
};
autosize.update = function (el) {
return el;
};
} else {
autosize = function autosize(el, options) {
if (el) {
Array.prototype.forEach.call(el.length ? el : [el], function (x) {
return assign(x, options);
});
}
return el;
};
autosize.destroy = function (el) {
if (el) {
Array.prototype.forEach.call(el.length ? el : [el], destroy);
}
return el;
};
autosize.update = function (el) {
if (el) {
Array.prototype.forEach.call(el.length ? el : [el], update);
}
return el;
};
}
exports.default = autosize;
module.exports = exports['default'];
});
/***/ }),
/***/ 4462:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __assign = (this && this.__assign) || Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)
t[p[i]] = s[p[i]];
return t;
};
exports.__esModule = true;
var React = __webpack_require__(1609);
var PropTypes = __webpack_require__(5826);
var autosize = __webpack_require__(4306);
var _getLineHeight = __webpack_require__(461);
var getLineHeight = _getLineHeight;
var RESIZED = "autosize:resized";
/**
* A light replacement for built-in textarea component
* which automaticaly adjusts its height to match the content
*/
var TextareaAutosizeClass = /** @class */ (function (_super) {
__extends(TextareaAutosizeClass, _super);
function TextareaAutosizeClass() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.state = {
lineHeight: null
};
_this.textarea = null;
_this.onResize = function (e) {
if (_this.props.onResize) {
_this.props.onResize(e);
}
};
_this.updateLineHeight = function () {
if (_this.textarea) {
_this.setState({
lineHeight: getLineHeight(_this.textarea)
});
}
};
_this.onChange = function (e) {
var onChange = _this.props.onChange;
_this.currentValue = e.currentTarget.value;
onChange && onChange(e);
};
return _this;
}
TextareaAutosizeClass.prototype.componentDidMount = function () {
var _this = this;
var _a = this.props, maxRows = _a.maxRows, async = _a.async;
if (typeof maxRows === "number") {
this.updateLineHeight();
}
if (typeof maxRows === "number" || async) {
/*
the defer is needed to:
- force "autosize" to activate the scrollbar when this.props.maxRows is passed
- support StyledComponents (see #71)
*/
setTimeout(function () { return _this.textarea && autosize(_this.textarea); });
}
else {
this.textarea && autosize(this.textarea);
}
if (this.textarea) {
this.textarea.addEventListener(RESIZED, this.onResize);
}
};
TextareaAutosizeClass.prototype.componentWillUnmount = function () {
if (this.textarea) {
this.textarea.removeEventListener(RESIZED, this.onResize);
autosize.destroy(this.textarea);
}
};
TextareaAutosizeClass.prototype.render = function () {
var _this = this;
var _a = this, _b = _a.props, onResize = _b.onResize, maxRows = _b.maxRows, onChange = _b.onChange, style = _b.style, innerRef = _b.innerRef, children = _b.children, props = __rest(_b, ["onResize", "maxRows", "onChange", "style", "innerRef", "children"]), lineHeight = _a.state.lineHeight;
var maxHeight = maxRows && lineHeight ? lineHeight * maxRows : null;
return (React.createElement("textarea", __assign({}, props, { onChange: this.onChange, style: maxHeight ? __assign({}, style, { maxHeight: maxHeight }) : style, ref: function (element) {
_this.textarea = element;
if (typeof _this.props.innerRef === 'function') {
_this.props.innerRef(element);
}
else if (_this.props.innerRef) {
_this.props.innerRef.current = element;
}
} }), children));
};
TextareaAutosizeClass.prototype.componentDidUpdate = function () {
this.textarea && autosize.update(this.textarea);
};
TextareaAutosizeClass.defaultProps = {
rows: 1,
async: false
};
TextareaAutosizeClass.propTypes = {
rows: PropTypes.number,
maxRows: PropTypes.number,
onResize: PropTypes.func,
innerRef: PropTypes.any,
async: PropTypes.bool
};
return TextareaAutosizeClass;
}(React.Component));
exports.TextareaAutosize = React.forwardRef(function (props, ref) {
return React.createElement(TextareaAutosizeClass, __assign({}, props, { innerRef: ref }));
});
/***/ }),
/***/ 4725:
/***/ ((module) => {
function stringifyNode(node, custom) {
var type = node.type;
var value = node.value;
var buf;
var customResult;
if (custom && (customResult = custom(node)) !== undefined) {
return customResult;
} else if (type === "word" || type === "space") {
return value;
} else if (type === "string") {
buf = node.quote || "";
return buf + value + (node.unclosed ? "" : buf);
} else if (type === "comment") {
return "/*" + value + (node.unclosed ? "" : "*/");
} else if (type === "div") {
return (node.before || "") + value + (node.after || "");
} else if (Array.isArray(node.nodes)) {
buf = stringify(node.nodes, custom);
if (type !== "function") {
return buf;
}
return (
value +
"(" +
(node.before || "") +
buf +
(node.after || "") +
(node.unclosed ? "" : ")")
);
}
return value;
}
function stringify(nodes, custom) {
var result, i;
if (Array.isArray(nodes)) {
result = "";
for (i = nodes.length - 1; ~i; i -= 1) {
result = stringifyNode(nodes[i], custom) + result;
}
return result;
}
return stringifyNode(nodes, custom);
}
module.exports = stringify;
/***/ }),
/***/ 5042:
/***/ ((module) => {
// This alphabet uses `A-Za-z0-9_-` symbols.
// The order of characters is optimized for better gzip and brotli compression.
// References to the same file (works both for gzip and brotli):
// `'use`, `andom`, and `rict'`
// References to the brotli default dictionary:
// `-26T`, `1983`, `40px`, `75px`, `bush`, `jack`, `mind`, `very`, and `wolf`
let urlAlphabet =
'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'
let customAlphabet = (alphabet, defaultSize = 21) => {
return (size = defaultSize) => {
let id = ''
// A compact alternative for `for (var i = 0; i < step; i++)`.
let i = size | 0
while (i--) {
// `| 0` is more compact and faster than `Math.floor()`.
id += alphabet[(Math.random() * alphabet.length) | 0]
}
return id
}
}
let nanoid = (size = 21) => {
let id = ''
// A compact alternative for `for (var i = 0; i < step; i++)`.
let i = size | 0
while (i--) {
// `| 0` is more compact and faster than `Math.floor()`.
id += urlAlphabet[(Math.random() * 64) | 0]
}
return id
}
module.exports = { nanoid, customAlphabet }
/***/ }),
/***/ 5215:
/***/ ((module) => {
"use strict";
// do not edit .js files directly - edit src/index.jst
module.exports = function equal(a, b) {
if (a === b) return true;
if (a && b && typeof a == 'object' && typeof b == 'object') {
if (a.constructor !== b.constructor) return false;
var length, i, keys;
if (Array.isArray(a)) {
length = a.length;
if (length != b.length) return false;
for (i = length; i-- !== 0;)
if (!equal(a[i], b[i])) return false;
return true;
}
if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;
if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();
if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();
keys = Object.keys(a);
length = keys.length;
if (length !== Object.keys(b).length) return false;
for (i = length; i-- !== 0;)
if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;
for (i = length; i-- !== 0;) {
var key = keys[i];
if (!equal(a[key], b[key])) return false;
}
return true;
}
// true if both NaN, false otherwise
return a!==a && b!==b;
};
/***/ }),
/***/ 5380:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
let { nanoid } = __webpack_require__(5042)
let { isAbsolute, resolve } = __webpack_require__(197)
let { SourceMapConsumer, SourceMapGenerator } = __webpack_require__(1866)
let { fileURLToPath, pathToFileURL } = __webpack_require__(2739)
let CssSyntaxError = __webpack_require__(356)
let PreviousMap = __webpack_require__(5696)
let terminalHighlight = __webpack_require__(9746)
let fromOffsetCache = Symbol('fromOffsetCache')
let sourceMapAvailable = Boolean(SourceMapConsumer && SourceMapGenerator)
let pathAvailable = Boolean(resolve && isAbsolute)
class Input {
get from() {
return this.file || this.id
}
constructor(css, opts = {}) {
if (
css === null ||
typeof css === 'undefined' ||
(typeof css === 'object' && !css.toString)
) {
throw new Error(`PostCSS received ${css} instead of CSS string`)
}
this.css = css.toString()
if (this.css[0] === '\uFEFF' || this.css[0] === '\uFFFE') {
this.hasBOM = true
this.css = this.css.slice(1)
} else {
this.hasBOM = false
}
this.document = this.css
if (opts.document) this.document = opts.document.toString()
if (opts.from) {
if (
!pathAvailable ||
/^\w+:\/\//.test(opts.from) ||
isAbsolute(opts.from)
) {
this.file = opts.from
} else {
this.file = resolve(opts.from)
}
}
if (pathAvailable && sourceMapAvailable) {
let map = new PreviousMap(this.css, opts)
if (map.text) {
this.map = map
let file = map.consumer().file
if (!this.file && file) this.file = this.mapResolve(file)
}
}
if (!this.file) {
this.id = '<input css ' + nanoid(6) + '>'
}
if (this.map) this.map.file = this.from
}
error(message, line, column, opts = {}) {
let endColumn, endLine, result
if (line && typeof line === 'object') {
let start = line
let end = column
if (typeof start.offset === 'number') {
let pos = this.fromOffset(start.offset)
line = pos.line
column = pos.col
} else {
line = start.line
column = start.column
}
if (typeof end.offset === 'number') {
let pos = this.fromOffset(end.offset)
endLine = pos.line
endColumn = pos.col
} else {
endLine = end.line
endColumn = end.column
}
} else if (!column) {
let pos = this.fromOffset(line)
line = pos.line
column = pos.col
}
let origin = this.origin(line, column, endLine, endColumn)
if (origin) {
result = new CssSyntaxError(
message,
origin.endLine === undefined
? origin.line
: { column: origin.column, line: origin.line },
origin.endLine === undefined
? origin.column
: { column: origin.endColumn, line: origin.endLine },
origin.source,
origin.file,
opts.plugin
)
} else {
result = new CssSyntaxError(
message,
endLine === undefined ? line : { column, line },
endLine === undefined ? column : { column: endColumn, line: endLine },
this.css,
this.file,
opts.plugin
)
}
result.input = { column, endColumn, endLine, line, source: this.css }
if (this.file) {
if (pathToFileURL) {
result.input.url = pathToFileURL(this.file).toString()
}
result.input.file = this.file
}
return result
}
fromOffset(offset) {
let lastLine, lineToIndex
if (!this[fromOffsetCache]) {
let lines = this.css.split('\n')
lineToIndex = new Array(lines.length)
let prevIndex = 0
for (let i = 0, l = lines.length; i < l; i++) {
lineToIndex[i] = prevIndex
prevIndex += lines[i].length + 1
}
this[fromOffsetCache] = lineToIndex
} else {
lineToIndex = this[fromOffsetCache]
}
lastLine = lineToIndex[lineToIndex.length - 1]
let min = 0
if (offset >= lastLine) {
min = lineToIndex.length - 1
} else {
let max = lineToIndex.length - 2
let mid
while (min < max) {
mid = min + ((max - min) >> 1)
if (offset < lineToIndex[mid]) {
max = mid - 1
} else if (offset >= lineToIndex[mid + 1]) {
min = mid + 1
} else {
min = mid
break
}
}
}
return {
col: offset - lineToIndex[min] + 1,
line: min + 1
}
}
mapResolve(file) {
if (/^\w+:\/\//.test(file)) {
return file
}
return resolve(this.map.consumer().sourceRoot || this.map.root || '.', file)
}
origin(line, column, endLine, endColumn) {
if (!this.map) return false
let consumer = this.map.consumer()
let from = consumer.originalPositionFor({ column, line })
if (!from.source) return false
let to
if (typeof endLine === 'number') {
to = consumer.originalPositionFor({ column: endColumn, line: endLine })
}
let fromUrl
if (isAbsolute(from.source)) {
fromUrl = pathToFileURL(from.source)
} else {
fromUrl = new URL(
from.source,
this.map.consumer().sourceRoot || pathToFileURL(this.map.mapFile)
)
}
let result = {
column: from.column,
endColumn: to && to.column,
endLine: to && to.line,
line: from.line,
url: fromUrl.toString()
}
if (fromUrl.protocol === 'file:') {
if (fileURLToPath) {
result.file = fileURLToPath(fromUrl)
} else {
/* c8 ignore next 2 */
throw new Error(`file: protocol is not available in this PostCSS build`)
}
}
let source = consumer.sourceContentFor(from.source)
if (source) result.source = source
return result
}
toJSON() {
let json = {}
for (let name of ['hasBOM', 'css', 'file', 'id']) {
if (this[name] != null) {
json[name] = this[name]
}
}
if (this.map) {
json.map = { ...this.map }
if (json.map.consumerCache) {
json.map.consumerCache = undefined
}
}
return json
}
}
module.exports = Input
Input.default = Input
if (terminalHighlight && terminalHighlight.registerInput) {
terminalHighlight.registerInput(Input)
}
/***/ }),
/***/ 5404:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
const CSSValueParser = __webpack_require__(1544)
/**
* @type {import('postcss').PluginCreator}
*/
module.exports = (opts) => {
const DEFAULTS = {
skipHostRelativeUrls: true,
}
const config = Object.assign(DEFAULTS, opts)
return {
postcssPlugin: 'rebaseUrl',
Declaration(decl) {
// The faster way to find Declaration node
const parsedValue = CSSValueParser(decl.value)
let valueChanged = false
parsedValue.walk(node => {
if (node.type !== 'function' || node.value !== 'url') {
return
}
const urlVal = node.nodes[0].value
// bases relative URLs with rootUrl
const basedUrl = new URL(urlVal, opts.rootUrl)
// skip host-relative, already normalized URLs (e.g. `/images/image.jpg`, without `..`s)
if ((basedUrl.pathname === urlVal) && config.skipHostRelativeUrls) {
return false // skip this value
}
node.nodes[0].value = basedUrl.toString()
valueChanged = true
return false // do not walk deeper
})
if (valueChanged) {
decl.value = CSSValueParser.stringify(parsedValue)
}
}
}
}
module.exports.postcss = true
/***/ }),
/***/ 5417:
/***/ ((__unused_webpack_module, exports) => {
"use strict";
/*istanbul ignore start*/
Object.defineProperty(exports, "__esModule", ({
value: true
}));
exports["default"] = Diff;
/*istanbul ignore end*/
function Diff() {}
Diff.prototype = {
/*istanbul ignore start*/
/*istanbul ignore end*/
diff: function diff(oldString, newString) {
/*istanbul ignore start*/
var
/*istanbul ignore end*/
options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
var callback = options.callback;
if (typeof options === 'function') {
callback = options;
options = {};
}
this.options = options;
var self = this;
function done(value) {
if (callback) {
setTimeout(function () {
callback(undefined, value);
}, 0);
return true;
} else {
return value;
}
} // Allow subclasses to massage the input prior to running
oldString = this.castInput(oldString);
newString = this.castInput(newString);
oldString = this.removeEmpty(this.tokenize(oldString));
newString = this.removeEmpty(this.tokenize(newString));
var newLen = newString.length,
oldLen = oldString.length;
var editLength = 1;
var maxEditLength = newLen + oldLen;
var bestPath = [{
newPos: -1,
components: []
}]; // Seed editLength = 0, i.e. the content starts with the same values
var oldPos = this.extractCommon(bestPath[0], newString, oldString, 0);
if (bestPath[0].newPos + 1 >= newLen && oldPos + 1 >= oldLen) {
// Identity per the equality and tokenizer
return done([{
value: this.join(newString),
count: newString.length
}]);
} // Main worker method. checks all permutations of a given edit length for acceptance.
function execEditLength() {
for (var diagonalPath = -1 * editLength; diagonalPath <= editLength; diagonalPath += 2) {
var basePath =
/*istanbul ignore start*/
void 0
/*istanbul ignore end*/
;
var addPath = bestPath[diagonalPath - 1],
removePath = bestPath[diagonalPath + 1],
_oldPos = (removePath ? removePath.newPos : 0) - diagonalPath;
if (addPath) {
// No one else is going to attempt to use this value, clear it
bestPath[diagonalPath - 1] = undefined;
}
var canAdd = addPath && addPath.newPos + 1 < newLen,
canRemove = removePath && 0 <= _oldPos && _oldPos < oldLen;
if (!canAdd && !canRemove) {
// If this path is a terminal then prune
bestPath[diagonalPath] = undefined;
continue;
} // Select the diagonal that we want to branch from. We select the prior
// path whose position in the new string is the farthest from the origin
// and does not pass the bounds of the diff graph
if (!canAdd || canRemove && addPath.newPos < removePath.newPos) {
basePath = clonePath(removePath);
self.pushComponent(basePath.components, undefined, true);
} else {
basePath = addPath; // No need to clone, we've pulled it from the list
basePath.newPos++;
self.pushComponent(basePath.components, true, undefined);
}
_oldPos = self.extractCommon(basePath, newString, oldString, diagonalPath); // If we have hit the end of both strings, then we are done
if (basePath.newPos + 1 >= newLen && _oldPos + 1 >= oldLen) {
return done(buildValues(self, basePath.components, newString, oldString, self.useLongestToken));
} else {
// Otherwise track this path as a potential candidate and continue.
bestPath[diagonalPath] = basePath;
}
}
editLength++;
} // Performs the length of edit iteration. Is a bit fugly as this has to support the
// sync and async mode which is never fun. Loops over execEditLength until a value
// is produced.
if (callback) {
(function exec() {
setTimeout(function () {
// This should not happen, but we want to be safe.
/* istanbul ignore next */
if (editLength > maxEditLength) {
return callback();
}
if (!execEditLength()) {
exec();
}
}, 0);
})();
} else {
while (editLength <= maxEditLength) {
var ret = execEditLength();
if (ret) {
return ret;
}
}
}
},
/*istanbul ignore start*/
/*istanbul ignore end*/
pushComponent: function pushComponent(components, added, removed) {
var last = components[components.length - 1];
if (last && last.added === added && last.removed === removed) {
// We need to clone here as the component clone operation is just
// as shallow array clone
components[components.length - 1] = {
count: last.count + 1,
added: added,
removed: removed
};
} else {
components.push({
count: 1,
added: added,
removed: removed
});
}
},
/*istanbul ignore start*/
/*istanbul ignore end*/
extractCommon: function extractCommon(basePath, newString, oldString, diagonalPath) {
var newLen = newString.length,
oldLen = oldString.length,
newPos = basePath.newPos,
oldPos = newPos - diagonalPath,
commonCount = 0;
while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(newString[newPos + 1], oldString[oldPos + 1])) {
newPos++;
oldPos++;
commonCount++;
}
if (commonCount) {
basePath.components.push({
count: commonCount
});
}
basePath.newPos = newPos;
return oldPos;
},
/*istanbul ignore start*/
/*istanbul ignore end*/
equals: function equals(left, right) {
if (this.options.comparator) {
return this.options.comparator(left, right);
} else {
return left === right || this.options.ignoreCase && left.toLowerCase() === right.toLowerCase();
}
},
/*istanbul ignore start*/
/*istanbul ignore end*/
removeEmpty: function removeEmpty(array) {
var ret = [];
for (var i = 0; i < array.length; i++) {
if (array[i]) {
ret.push(array[i]);
}
}
return ret;
},
/*istanbul ignore start*/
/*istanbul ignore end*/
castInput: function castInput(value) {
return value;
},
/*istanbul ignore start*/
/*istanbul ignore end*/
tokenize: function tokenize(value) {
return value.split('');
},
/*istanbul ignore start*/
/*istanbul ignore end*/
join: function join(chars) {
return chars.join('');
}
};
function buildValues(diff, components, newString, oldString, useLongestToken) {
var componentPos = 0,
componentLen = components.length,
newPos = 0,
oldPos = 0;
for (; componentPos < componentLen; componentPos++) {
var component = components[componentPos];
if (!component.removed) {
if (!component.added && useLongestToken) {
var value = newString.slice(newPos, newPos + component.count);
value = value.map(function (value, i) {
var oldValue = oldString[oldPos + i];
return oldValue.length > value.length ? oldValue : value;
});
component.value = diff.join(value);
} else {
component.value = diff.join(newString.slice(newPos, newPos + component.count));
}
newPos += component.count; // Common case
if (!component.added) {
oldPos += component.count;
}
} else {
component.value = diff.join(oldString.slice(oldPos, oldPos + component.count));
oldPos += component.count; // Reverse add and remove so removes are output first to match common convention
// The diffing algorithm is tied to add then remove output and this is the simplest
// route to get the desired output with minimal overhead.
if (componentPos && components[componentPos - 1].added) {
var tmp = components[componentPos - 1];
components[componentPos - 1] = components[componentPos];
components[componentPos] = tmp;
}
}
} // Special case handle for when one terminal is ignored (i.e. whitespace).
// For this case we merge the terminal into the prior string and drop the change.
// This is only available for string mode.
var lastComponent = components[componentLen - 1];
if (componentLen > 1 && typeof lastComponent.value === 'string' && (lastComponent.added || lastComponent.removed) && diff.equals('', lastComponent.value)) {
components[componentLen - 2].value += lastComponent.value;
components.pop();
}
return components;
}
function clonePath(path) {
return {
newPos: path.newPos,
components: path.components.slice(0)
};
}
/***/ }),
/***/ 5696:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
let { existsSync, readFileSync } = __webpack_require__(9977)
let { dirname, join } = __webpack_require__(197)
let { SourceMapConsumer, SourceMapGenerator } = __webpack_require__(1866)
function fromBase64(str) {
if (Buffer) {
return Buffer.from(str, 'base64').toString()
} else {
/* c8 ignore next 2 */
return window.atob(str)
}
}
class PreviousMap {
constructor(css, opts) {
if (opts.map === false) return
this.loadAnnotation(css)
this.inline = this.startWith(this.annotation, 'data:')
let prev = opts.map ? opts.map.prev : undefined
let text = this.loadMap(opts.from, prev)
if (!this.mapFile && opts.from) {
this.mapFile = opts.from
}
if (this.mapFile) this.root = dirname(this.mapFile)
if (text) this.text = text
}
consumer() {
if (!this.consumerCache) {
this.consumerCache = new SourceMapConsumer(this.text)
}
return this.consumerCache
}
decodeInline(text) {
let baseCharsetUri = /^data:application\/json;charset=utf-?8;base64,/
let baseUri = /^data:application\/json;base64,/
let charsetUri = /^data:application\/json;charset=utf-?8,/
let uri = /^data:application\/json,/
let uriMatch = text.match(charsetUri) || text.match(uri)
if (uriMatch) {
return decodeURIComponent(text.substr(uriMatch[0].length))
}
let baseUriMatch = text.match(baseCharsetUri) || text.match(baseUri)
if (baseUriMatch) {
return fromBase64(text.substr(baseUriMatch[0].length))
}
let encoding = text.match(/data:application\/json;([^,]+),/)[1]
throw new Error('Unsupported source map encoding ' + encoding)
}
getAnnotationURL(sourceMapString) {
return sourceMapString.replace(/^\/\*\s*# sourceMappingURL=/, '').trim()
}
isMap(map) {
if (typeof map !== 'object') return false
return (
typeof map.mappings === 'string' ||
typeof map._mappings === 'string' ||
Array.isArray(map.sections)
)
}
loadAnnotation(css) {
let comments = css.match(/\/\*\s*# sourceMappingURL=/g)
if (!comments) return
// sourceMappingURLs from comments, strings, etc.
let start = css.lastIndexOf(comments.pop())
let end = css.indexOf('*/', start)
if (start > -1 && end > -1) {
// Locate the last sourceMappingURL to avoid pickin
this.annotation = this.getAnnotationURL(css.substring(start, end))
}
}
loadFile(path) {
this.root = dirname(path)
if (existsSync(path)) {
this.mapFile = path
return readFileSync(path, 'utf-8').toString().trim()
}
}
loadMap(file, prev) {
if (prev === false) return false
if (prev) {
if (typeof prev === 'string') {
return prev
} else if (typeof prev === 'function') {
let prevPath = prev(file)
if (prevPath) {
let map = this.loadFile(prevPath)
if (!map) {
throw new Error(
'Unable to load previous source map: ' + prevPath.toString()
)
}
return map
}
} else if (prev instanceof SourceMapConsumer) {
return SourceMapGenerator.fromSourceMap(prev).toString()
} else if (prev instanceof SourceMapGenerator) {
return prev.toString()
} else if (this.isMap(prev)) {
return JSON.stringify(prev)
} else {
throw new Error(
'Unsupported previous source map format: ' + prev.toString()
)
}
} else if (this.inline) {
return this.decodeInline(this.annotation)
} else if (this.annotation) {
let map = this.annotation
if (file) map = join(dirname(file), map)
return this.loadFile(map)
}
}
startWith(string, start) {
if (!string) return false
return string.substr(0, start.length) === start
}
withContent() {
return !!(
this.consumer().sourcesContent &&
this.consumer().sourcesContent.length > 0
)
}
}
module.exports = PreviousMap
PreviousMap.default = PreviousMap
/***/ }),
/***/ 5776:
/***/ ((module) => {
"use strict";
class Warning {
constructor(text, opts = {}) {
this.type = 'warning'
this.text = text
if (opts.node && opts.node.source) {
let range = opts.node.rangeBy(opts)
this.line = range.start.line
this.column = range.start.column
this.endLine = range.end.line
this.endColumn = range.end.column
}
for (let opt in opts) this[opt] = opts[opt]
}
toString() {
if (this.node) {
return this.node.error(this.text, {
index: this.index,
plugin: this.plugin,
word: this.word
}).message
}
if (this.plugin) {
return this.plugin + ': ' + this.text
}
return this.text
}
}
module.exports = Warning
Warning.default = Warning
/***/ }),
/***/ 5826:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
if (false) { var throwOnDirectAccess, ReactIs; } else {
// By explicitly using `prop-types` you are opting into new production behavior.
// http://fb.me/prop-types-in-prod
module.exports = __webpack_require__(628)();
}
/***/ }),
/***/ 6109:
/***/ ((module) => {
// This code has been refactored for 140 bytes
// You can see the original here: https://github.com/twolfson/computedStyle/blob/04cd1da2e30fa45844f95f5cb1ac898e9b9ef050/lib/computedStyle.js
var computedStyle = function (el, prop, getComputedStyle) {
getComputedStyle = window.getComputedStyle;
// In one fell swoop
return (
// If we have getComputedStyle
getComputedStyle ?
// Query it
// TODO: From CSS-Query notes, we might need (node, null) for FF
getComputedStyle(el) :
// Otherwise, we are in IE and use currentStyle
el.currentStyle
)[
// Switch to camelCase for CSSOM
// DEV: Grabbed from jQuery
// https://github.com/jquery/jquery/blob/1.9-stable/src/css.js#L191-L194
// https://github.com/jquery/jquery/blob/1.9-stable/src/core.js#L593-L597
prop.replace(/-(\w)/gi, function (word, letter) {
return letter.toUpperCase();
})
];
};
module.exports = computedStyle;
/***/ }),
/***/ 6589:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
let Node = __webpack_require__(7490)
class Comment extends Node {
constructor(defaults) {
super(defaults)
this.type = 'comment'
}
}
module.exports = Comment
Comment.default = Comment
/***/ }),
/***/ 7191:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
/**
* Copyright (c) 2015, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule normalizeWheel
* @typechecks
*/
var UserAgent_DEPRECATED = __webpack_require__(2213);
var isEventSupported = __webpack_require__(1087);
// Reasonable defaults
var PIXEL_STEP = 10;
var LINE_HEIGHT = 40;
var PAGE_HEIGHT = 800;
/**
* Mouse wheel (and 2-finger trackpad) support on the web sucks. It is
* complicated, thus this doc is long and (hopefully) detailed enough to answer
* your questions.
*
* If you need to react to the mouse wheel in a predictable way, this code is
* like your bestest friend. * hugs *
*
* As of today, there are 4 DOM event types you can listen to:
*
* 'wheel' -- Chrome(31+), FF(17+), IE(9+)
* 'mousewheel' -- Chrome, IE(6+), Opera, Safari
* 'MozMousePixelScroll' -- FF(3.5 only!) (2010-2013) -- don't bother!
* 'DOMMouseScroll' -- FF(0.9.7+) since 2003
*
* So what to do? The is the best:
*
* normalizeWheel.getEventType();
*
* In your event callback, use this code to get sane interpretation of the
* deltas. This code will return an object with properties:
*
* spinX -- normalized spin speed (use for zoom) - x plane
* spinY -- " - y plane
* pixelX -- normalized distance (to pixels) - x plane
* pixelY -- " - y plane
*
* Wheel values are provided by the browser assuming you are using the wheel to
* scroll a web page by a number of lines or pixels (or pages). Values can vary
* significantly on different platforms and browsers, forgetting that you can
* scroll at different speeds. Some devices (like trackpads) emit more events
* at smaller increments with fine granularity, and some emit massive jumps with
* linear speed or acceleration.
*
* This code does its best to normalize the deltas for you:
*
* - spin is trying to normalize how far the wheel was spun (or trackpad
* dragged). This is super useful for zoom support where you want to
* throw away the chunky scroll steps on the PC and make those equal to
* the slow and smooth tiny steps on the Mac. Key data: This code tries to
* resolve a single slow step on a wheel to 1.
*
* - pixel is normalizing the desired scroll delta in pixel units. You'll
* get the crazy differences between browsers, but at least it'll be in
* pixels!
*
* - positive value indicates scrolling DOWN/RIGHT, negative UP/LEFT. This
* should translate to positive value zooming IN, negative zooming OUT.
* This matches the newer 'wheel' event.
*
* Why are there spinX, spinY (or pixels)?
*
* - spinX is a 2-finger side drag on the trackpad, and a shift + wheel turn
* with a mouse. It results in side-scrolling in the browser by default.
*
* - spinY is what you expect -- it's the classic axis of a mouse wheel.
*
* - I dropped spinZ/pixelZ. It is supported by the DOM 3 'wheel' event and
* probably is by browsers in conjunction with fancy 3D controllers .. but
* you know.
*
* Implementation info:
*
* Examples of 'wheel' event if you scroll slowly (down) by one step with an
* average mouse:
*
* OS X + Chrome (mouse) - 4 pixel delta (wheelDelta -120)
* OS X + Safari (mouse) - N/A pixel delta (wheelDelta -12)
* OS X + Firefox (mouse) - 0.1 line delta (wheelDelta N/A)
* Win8 + Chrome (mouse) - 100 pixel delta (wheelDelta -120)
* Win8 + Firefox (mouse) - 3 line delta (wheelDelta -120)
*
* On the trackpad:
*
* OS X + Chrome (trackpad) - 2 pixel delta (wheelDelta -6)
* OS X + Firefox (trackpad) - 1 pixel delta (wheelDelta N/A)
*
* On other/older browsers.. it's more complicated as there can be multiple and
* also missing delta values.
*
* The 'wheel' event is more standard:
*
* http://www.w3.org/TR/DOM-Level-3-Events/#events-wheelevents
*
* The basics is that it includes a unit, deltaMode (pixels, lines, pages), and
* deltaX, deltaY and deltaZ. Some browsers provide other values to maintain
* backward compatibility with older events. Those other values help us
* better normalize spin speed. Example of what the browsers provide:
*
* | event.wheelDelta | event.detail
* ------------------+------------------+--------------
* Safari v5/OS X | -120 | 0
* Safari v5/Win7 | -120 | 0
* Chrome v17/OS X | -120 | 0
* Chrome v17/Win7 | -120 | 0
* IE9/Win7 | -120 | undefined
* Firefox v4/OS X | undefined | 1
* Firefox v4/Win7 | undefined | 3
*
*/
function normalizeWheel(/*object*/ event) /*object*/ {
var sX = 0, sY = 0, // spinX, spinY
pX = 0, pY = 0; // pixelX, pixelY
// Legacy
if ('detail' in event) { sY = event.detail; }
if ('wheelDelta' in event) { sY = -event.wheelDelta / 120; }
if ('wheelDeltaY' in event) { sY = -event.wheelDeltaY / 120; }
if ('wheelDeltaX' in event) { sX = -event.wheelDeltaX / 120; }
// side scrolling on FF with DOMMouseScroll
if ( 'axis' in event && event.axis === event.HORIZONTAL_AXIS ) {
sX = sY;
sY = 0;
}
pX = sX * PIXEL_STEP;
pY = sY * PIXEL_STEP;
if ('deltaY' in event) { pY = event.deltaY; }
if ('deltaX' in event) { pX = event.deltaX; }
if ((pX || pY) && event.deltaMode) {
if (event.deltaMode == 1) { // delta in LINE units
pX *= LINE_HEIGHT;
pY *= LINE_HEIGHT;
} else { // delta in PAGE units
pX *= PAGE_HEIGHT;
pY *= PAGE_HEIGHT;
}
}
// Fall-back if spin cannot be determined
if (pX && !sX) { sX = (pX < 1) ? -1 : 1; }
if (pY && !sY) { sY = (pY < 1) ? -1 : 1; }
return { spinX : sX,
spinY : sY,
pixelX : pX,
pixelY : pY };
}
/**
* The best combination if you prefer spinX + spinY normalization. It favors
* the older DOMMouseScroll for Firefox, as FF does not include wheelDelta with
* 'wheel' event, making spin speed determination impossible.
*/
normalizeWheel.getEventType = function() /*string*/ {
return (UserAgent_DEPRECATED.firefox())
? 'DOMMouseScroll'
: (isEventSupported('wheel'))
? 'wheel'
: 'mousewheel';
};
module.exports = normalizeWheel;
/***/ }),
/***/ 7374:
/***/ ((module) => {
"use strict";
let list = {
comma(string) {
return list.split(string, [','], true)
},
space(string) {
let spaces = [' ', '\n', '\t']
return list.split(string, spaces)
},
split(string, separators, last) {
let array = []
let current = ''
let split = false
let func = 0
let inQuote = false
let prevQuote = ''
let escape = false
for (let letter of string) {
if (escape) {
escape = false
} else if (letter === '\\') {
escape = true
} else if (inQuote) {
if (letter === prevQuote) {
inQuote = false
}
} else if (letter === '"' || letter === "'") {
inQuote = true
prevQuote = letter
} else if (letter === '(') {
func += 1
} else if (letter === ')') {
if (func > 0) func -= 1
} else if (func === 0) {
if (separators.includes(letter)) split = true
}
if (split) {
if (current !== '') array.push(current.trim())
current = ''
split = false
} else {
current += letter
}
}
if (last || current !== '') array.push(current.trim())
return array
}
}
module.exports = list
list.default = list
/***/ }),
/***/ 7490:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
let CssSyntaxError = __webpack_require__(356)
let Stringifier = __webpack_require__(346)
let stringify = __webpack_require__(633)
let { isClean, my } = __webpack_require__(1381)
function cloneNode(obj, parent) {
let cloned = new obj.constructor()
for (let i in obj) {
if (!Object.prototype.hasOwnProperty.call(obj, i)) {
/* c8 ignore next 2 */
continue
}
if (i === 'proxyCache') continue
let value = obj[i]
let type = typeof value
if (i === 'parent' && type === 'object') {
if (parent) cloned[i] = parent
} else if (i === 'source') {
cloned[i] = value
} else if (Array.isArray(value)) {
cloned[i] = value.map(j => cloneNode(j, cloned))
} else {
if (type === 'object' && value !== null) value = cloneNode(value)
cloned[i] = value
}
}
return cloned
}
function sourceOffset(inputCSS, position) {
// Not all custom syntaxes support `offset` in `source.start` and `source.end`
if (
position &&
typeof position.offset !== 'undefined'
) {
return position.offset;
}
let column = 1
let line = 1
let offset = 0
for (let i = 0; i < inputCSS.length; i++) {
if (line === position.line && column === position.column) {
offset = i
break
}
if (inputCSS[i] === '\n') {
column = 1
line += 1
} else {
column += 1
}
}
return offset
}
class Node {
get proxyOf() {
return this
}
constructor(defaults = {}) {
this.raws = {}
this[isClean] = false
this[my] = true
for (let name in defaults) {
if (name === 'nodes') {
this.nodes = []
for (let node of defaults[name]) {
if (typeof node.clone === 'function') {
this.append(node.clone())
} else {
this.append(node)
}
}
} else {
this[name] = defaults[name]
}
}
}
addToError(error) {
error.postcssNode = this
if (error.stack && this.source && /\n\s{4}at /.test(error.stack)) {
let s = this.source
error.stack = error.stack.replace(
/\n\s{4}at /,
`$&${s.input.from}:${s.start.line}:${s.start.column}$&`
)
}
return error
}
after(add) {
this.parent.insertAfter(this, add)
return this
}
assign(overrides = {}) {
for (let name in overrides) {
this[name] = overrides[name]
}
return this
}
before(add) {
this.parent.insertBefore(this, add)
return this
}
cleanRaws(keepBetween) {
delete this.raws.before
delete this.raws.after
if (!keepBetween) delete this.raws.between
}
clone(overrides = {}) {
let cloned = cloneNode(this)
for (let name in overrides) {
cloned[name] = overrides[name]
}
return cloned
}
cloneAfter(overrides = {}) {
let cloned = this.clone(overrides)
this.parent.insertAfter(this, cloned)
return cloned
}
cloneBefore(overrides = {}) {
let cloned = this.clone(overrides)
this.parent.insertBefore(this, cloned)
return cloned
}
error(message, opts = {}) {
if (this.source) {
let { end, start } = this.rangeBy(opts)
return this.source.input.error(
message,
{ column: start.column, line: start.line },
{ column: end.column, line: end.line },
opts
)
}
return new CssSyntaxError(message)
}
getProxyProcessor() {
return {
get(node, prop) {
if (prop === 'proxyOf') {
return node
} else if (prop === 'root') {
return () => node.root().toProxy()
} else {
return node[prop]
}
},
set(node, prop, value) {
if (node[prop] === value) return true
node[prop] = value
if (
prop === 'prop' ||
prop === 'value' ||
prop === 'name' ||
prop === 'params' ||
prop === 'important' ||
/* c8 ignore next */
prop === 'text'
) {
node.markDirty()
}
return true
}
}
}
/* c8 ignore next 3 */
markClean() {
this[isClean] = true
}
markDirty() {
if (this[isClean]) {
this[isClean] = false
let next = this
while ((next = next.parent)) {
next[isClean] = false
}
}
}
next() {
if (!this.parent) return undefined
let index = this.parent.index(this)
return this.parent.nodes[index + 1]
}
positionBy(opts) {
let pos = this.source.start
if (opts.index) {
pos = this.positionInside(opts.index)
} else if (opts.word) {
let inputString = ('document' in this.source.input)
? this.source.input.document
: this.source.input.css
let stringRepresentation = inputString.slice(
sourceOffset(inputString, this.source.start),
sourceOffset(inputString, this.source.end)
)
let index = stringRepresentation.indexOf(opts.word)
if (index !== -1) pos = this.positionInside(index)
}
return pos
}
positionInside(index) {
let column = this.source.start.column
let line = this.source.start.line
let inputString = ('document' in this.source.input)
? this.source.input.document
: this.source.input.css
let offset = sourceOffset(inputString, this.source.start)
let end = offset + index
for (let i = offset; i < end; i++) {
if (inputString[i] === '\n') {
column = 1
line += 1
} else {
column += 1
}
}
return { column, line }
}
prev() {
if (!this.parent) return undefined
let index = this.parent.index(this)
return this.parent.nodes[index - 1]
}
rangeBy(opts) {
let start = {
column: this.source.start.column,
line: this.source.start.line
}
let end = this.source.end
? {
column: this.source.end.column + 1,
line: this.source.end.line
}
: {
column: start.column + 1,
line: start.line
}
if (opts.word) {
let inputString = ('document' in this.source.input)
? this.source.input.document
: this.source.input.css
let stringRepresentation = inputString.slice(
sourceOffset(inputString, this.source.start),
sourceOffset(inputString, this.source.end)
)
let index = stringRepresentation.indexOf(opts.word)
if (index !== -1) {
start = this.positionInside(index)
end = this.positionInside(
index + opts.word.length,
)
}
} else {
if (opts.start) {
start = {
column: opts.start.column,
line: opts.start.line
}
} else if (opts.index) {
start = this.positionInside(opts.index)
}
if (opts.end) {
end = {
column: opts.end.column,
line: opts.end.line
}
} else if (typeof opts.endIndex === 'number') {
end = this.positionInside(opts.endIndex)
} else if (opts.index) {
end = this.positionInside(opts.index + 1)
}
}
if (
end.line < start.line ||
(end.line === start.line && end.column <= start.column)
) {
end = { column: start.column + 1, line: start.line }
}
return { end, start }
}
raw(prop, defaultType) {
let str = new Stringifier()
return str.raw(this, prop, defaultType)
}
remove() {
if (this.parent) {
this.parent.removeChild(this)
}
this.parent = undefined
return this
}
replaceWith(...nodes) {
if (this.parent) {
let bookmark = this
let foundSelf = false
for (let node of nodes) {
if (node === this) {
foundSelf = true
} else if (foundSelf) {
this.parent.insertAfter(bookmark, node)
bookmark = node
} else {
this.parent.insertBefore(bookmark, node)
}
}
if (!foundSelf) {
this.remove()
}
}
return this
}
root() {
let result = this
while (result.parent && result.parent.type !== 'document') {
result = result.parent
}
return result
}
toJSON(_, inputs) {
let fixed = {}
let emitInputs = inputs == null
inputs = inputs || new Map()
let inputsNextIndex = 0
for (let name in this) {
if (!Object.prototype.hasOwnProperty.call(this, name)) {
/* c8 ignore next 2 */
continue
}
if (name === 'parent' || name === 'proxyCache') continue
let value = this[name]
if (Array.isArray(value)) {
fixed[name] = value.map(i => {
if (typeof i === 'object' && i.toJSON) {
return i.toJSON(null, inputs)
} else {
return i
}
})
} else if (typeof value === 'object' && value.toJSON) {
fixed[name] = value.toJSON(null, inputs)
} else if (name === 'source') {
let inputId = inputs.get(value.input)
if (inputId == null) {
inputId = inputsNextIndex
inputs.set(value.input, inputsNextIndex)
inputsNextIndex++
}
fixed[name] = {
end: value.end,
inputId,
start: value.start
}
} else {
fixed[name] = value
}
}
if (emitInputs) {
fixed.inputs = [...inputs.keys()].map(input => input.toJSON())
}
return fixed
}
toProxy() {
if (!this.proxyCache) {
this.proxyCache = new Proxy(this, this.getProxyProcessor())
}
return this.proxyCache
}
toString(stringifier = stringify) {
if (stringifier.stringify) stringifier = stringifier.stringify
let result = ''
stringifier(this, i => {
result += i
})
return result
}
warn(result, text, opts) {
let data = { node: this }
for (let i in opts) data[i] = opts[i]
return result.warn(text, data)
}
}
module.exports = Node
Node.default = Node
/***/ }),
/***/ 7520:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
module.exports = __webpack_require__(7191);
/***/ }),
/***/ 7661:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
let MapGenerator = __webpack_require__(1670)
let parse = __webpack_require__(4295)
const Result = __webpack_require__(9055)
let stringify = __webpack_require__(633)
let warnOnce = __webpack_require__(3122)
class NoWorkResult {
get content() {
return this.result.css
}
get css() {
return this.result.css
}
get map() {
return this.result.map
}
get messages() {
return []
}
get opts() {
return this.result.opts
}
get processor() {
return this.result.processor
}
get root() {
if (this._root) {
return this._root
}
let root
let parser = parse
try {
root = parser(this._css, this._opts)
} catch (error) {
this.error = error
}
if (this.error) {
throw this.error
} else {
this._root = root
return root
}
}
get [Symbol.toStringTag]() {
return 'NoWorkResult'
}
constructor(processor, css, opts) {
css = css.toString()
this.stringified = false
this._processor = processor
this._css = css
this._opts = opts
this._map = undefined
let root
let str = stringify
this.result = new Result(this._processor, root, this._opts)
this.result.css = css
let self = this
Object.defineProperty(this.result, 'root', {
get() {
return self.root
}
})
let map = new MapGenerator(str, root, this._opts, css)
if (map.isMap()) {
let [generatedCSS, generatedMap] = map.generate()
if (generatedCSS) {
this.result.css = generatedCSS
}
if (generatedMap) {
this.result.map = generatedMap
}
} else {
map.clearAnnotation()
this.result.css = map.css
}
}
async() {
if (this.error) return Promise.reject(this.error)
return Promise.resolve(this.result)
}
catch(onRejected) {
return this.async().catch(onRejected)
}
finally(onFinally) {
return this.async().then(onFinally, onFinally)
}
sync() {
if (this.error) throw this.error
return this.result
}
then(onFulfilled, onRejected) {
if (false) {}
return this.async().then(onFulfilled, onRejected)
}
toString() {
return this._css
}
warnings() {
return []
}
}
module.exports = NoWorkResult
NoWorkResult.default = NoWorkResult
/***/ }),
/***/ 7734:
/***/ ((module) => {
"use strict";
// do not edit .js files directly - edit src/index.jst
var envHasBigInt64Array = typeof BigInt64Array !== 'undefined';
module.exports = function equal(a, b) {
if (a === b) return true;
if (a && b && typeof a == 'object' && typeof b == 'object') {
if (a.constructor !== b.constructor) return false;
var length, i, keys;
if (Array.isArray(a)) {
length = a.length;
if (length != b.length) return false;
for (i = length; i-- !== 0;)
if (!equal(a[i], b[i])) return false;
return true;
}
if ((a instanceof Map) && (b instanceof Map)) {
if (a.size !== b.size) return false;
for (i of a.entries())
if (!b.has(i[0])) return false;
for (i of a.entries())
if (!equal(i[1], b.get(i[0]))) return false;
return true;
}
if ((a instanceof Set) && (b instanceof Set)) {
if (a.size !== b.size) return false;
for (i of a.entries())
if (!b.has(i[0])) return false;
return true;
}
if (ArrayBuffer.isView(a) && ArrayBuffer.isView(b)) {
length = a.length;
if (length != b.length) return false;
for (i = length; i-- !== 0;)
if (a[i] !== b[i]) return false;
return true;
}
if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;
if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();
if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();
keys = Object.keys(a);
length = keys.length;
if (length !== Object.keys(b).length) return false;
for (i = length; i-- !== 0;)
if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;
for (i = length; i-- !== 0;) {
var key = keys[i];
if (!equal(a[key], b[key])) return false;
}
return true;
}
// true if both NaN, false otherwise
return a!==a && b!==b;
};
/***/ }),
/***/ 8021:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
"use strict";
var __webpack_unused_export__;
/*istanbul ignore start*/
__webpack_unused_export__ = ({
value: true
});
exports.JJ = diffChars;
__webpack_unused_export__ = void 0;
/*istanbul ignore end*/
var
/*istanbul ignore start*/
_base = _interopRequireDefault(__webpack_require__(5417))
/*istanbul ignore end*/
;
/*istanbul ignore start*/ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/*istanbul ignore end*/
var characterDiff = new
/*istanbul ignore start*/
_base
/*istanbul ignore end*/
.
/*istanbul ignore start*/
default
/*istanbul ignore end*/
();
/*istanbul ignore start*/
__webpack_unused_export__ = characterDiff;
/*istanbul ignore end*/
function diffChars(oldStr, newStr, options) {
return characterDiff.diff(oldStr, newStr, options);
}
/***/ }),
/***/ 8202:
/***/ ((module) => {
"use strict";
/**
* Copyright (c) 2015, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ExecutionEnvironment
*/
/*jslint evil: true */
var canUseDOM = !!(
typeof window !== 'undefined' &&
window.document &&
window.document.createElement
);
/**
* Simple, lightweight module assisting with the detection and context of
* Worker. Helps avoid circular dependencies and allows code to reason about
* whether or not they are in a Worker, even if they never include the main
* `ReactWorker` dependency.
*/
var ExecutionEnvironment = {
canUseDOM: canUseDOM,
canUseWorkers: typeof Worker !== 'undefined',
canUseEventListeners:
canUseDOM && !!(window.addEventListener || window.attachEvent),
canUseViewport: canUseDOM && !!window.screen,
isInWorker: !canUseDOM // For now, this is true - might change in the future.
};
module.exports = ExecutionEnvironment;
/***/ }),
/***/ 8491:
/***/ ((module) => {
var openParentheses = "(".charCodeAt(0);
var closeParentheses = ")".charCodeAt(0);
var singleQuote = "'".charCodeAt(0);
var doubleQuote = '"'.charCodeAt(0);
var backslash = "\\".charCodeAt(0);
var slash = "/".charCodeAt(0);
var comma = ",".charCodeAt(0);
var colon = ":".charCodeAt(0);
var star = "*".charCodeAt(0);
var uLower = "u".charCodeAt(0);
var uUpper = "U".charCodeAt(0);
var plus = "+".charCodeAt(0);
var isUnicodeRange = /^[a-f0-9?-]+$/i;
module.exports = function(input) {
var tokens = [];
var value = input;
var next,
quote,
prev,
token,
escape,
escapePos,
whitespacePos,
parenthesesOpenPos;
var pos = 0;
var code = value.charCodeAt(pos);
var max = value.length;
var stack = [{ nodes: tokens }];
var balanced = 0;
var parent;
var name = "";
var before = "";
var after = "";
while (pos < max) {
// Whitespaces
if (code <= 32) {
next = pos;
do {
next += 1;
code = value.charCodeAt(next);
} while (code <= 32);
token = value.slice(pos, next);
prev = tokens[tokens.length - 1];
if (code === closeParentheses && balanced) {
after = token;
} else if (prev && prev.type === "div") {
prev.after = token;
prev.sourceEndIndex += token.length;
} else if (
code === comma ||
code === colon ||
(code === slash &&
value.charCodeAt(next + 1) !== star &&
(!parent ||
(parent && parent.type === "function" && parent.value !== "calc")))
) {
before = token;
} else {
tokens.push({
type: "space",
sourceIndex: pos,
sourceEndIndex: next,
value: token
});
}
pos = next;
// Quotes
} else if (code === singleQuote || code === doubleQuote) {
next = pos;
quote = code === singleQuote ? "'" : '"';
token = {
type: "string",
sourceIndex: pos,
quote: quote
};
do {
escape = false;
next = value.indexOf(quote, next + 1);
if (~next) {
escapePos = next;
while (value.charCodeAt(escapePos - 1) === backslash) {
escapePos -= 1;
escape = !escape;
}
} else {
value += quote;
next = value.length - 1;
token.unclosed = true;
}
} while (escape);
token.value = value.slice(pos + 1, next);
token.sourceEndIndex = token.unclosed ? next : next + 1;
tokens.push(token);
pos = next + 1;
code = value.charCodeAt(pos);
// Comments
} else if (code === slash && value.charCodeAt(pos + 1) === star) {
next = value.indexOf("*/", pos);
token = {
type: "comment",
sourceIndex: pos,
sourceEndIndex: next + 2
};
if (next === -1) {
token.unclosed = true;
next = value.length;
token.sourceEndIndex = next;
}
token.value = value.slice(pos + 2, next);
tokens.push(token);
pos = next + 2;
code = value.charCodeAt(pos);
// Operation within calc
} else if (
(code === slash || code === star) &&
parent &&
parent.type === "function" &&
parent.value === "calc"
) {
token = value[pos];
tokens.push({
type: "word",
sourceIndex: pos - before.length,
sourceEndIndex: pos + token.length,
value: token
});
pos += 1;
code = value.charCodeAt(pos);
// Dividers
} else if (code === slash || code === comma || code === colon) {
token = value[pos];
tokens.push({
type: "div",
sourceIndex: pos - before.length,
sourceEndIndex: pos + token.length,
value: token,
before: before,
after: ""
});
before = "";
pos += 1;
code = value.charCodeAt(pos);
// Open parentheses
} else if (openParentheses === code) {
// Whitespaces after open parentheses
next = pos;
do {
next += 1;
code = value.charCodeAt(next);
} while (code <= 32);
parenthesesOpenPos = pos;
token = {
type: "function",
sourceIndex: pos - name.length,
value: name,
before: value.slice(parenthesesOpenPos + 1, next)
};
pos = next;
if (name === "url" && code !== singleQuote && code !== doubleQuote) {
next -= 1;
do {
escape = false;
next = value.indexOf(")", next + 1);
if (~next) {
escapePos = next;
while (value.charCodeAt(escapePos - 1) === backslash) {
escapePos -= 1;
escape = !escape;
}
} else {
value += ")";
next = value.length - 1;
token.unclosed = true;
}
} while (escape);
// Whitespaces before closed
whitespacePos = next;
do {
whitespacePos -= 1;
code = value.charCodeAt(whitespacePos);
} while (code <= 32);
if (parenthesesOpenPos < whitespacePos) {
if (pos !== whitespacePos + 1) {
token.nodes = [
{
type: "word",
sourceIndex: pos,
sourceEndIndex: whitespacePos + 1,
value: value.slice(pos, whitespacePos + 1)
}
];
} else {
token.nodes = [];
}
if (token.unclosed && whitespacePos + 1 !== next) {
token.after = "";
token.nodes.push({
type: "space",
sourceIndex: whitespacePos + 1,
sourceEndIndex: next,
value: value.slice(whitespacePos + 1, next)
});
} else {
token.after = value.slice(whitespacePos + 1, next);
token.sourceEndIndex = next;
}
} else {
token.after = "";
token.nodes = [];
}
pos = next + 1;
token.sourceEndIndex = token.unclosed ? next : pos;
code = value.charCodeAt(pos);
tokens.push(token);
} else {
balanced += 1;
token.after = "";
token.sourceEndIndex = pos + 1;
tokens.push(token);
stack.push(token);
tokens = token.nodes = [];
parent = token;
}
name = "";
// Close parentheses
} else if (closeParentheses === code && balanced) {
pos += 1;
code = value.charCodeAt(pos);
parent.after = after;
parent.sourceEndIndex += after.length;
after = "";
balanced -= 1;
stack[stack.length - 1].sourceEndIndex = pos;
stack.pop();
parent = stack[balanced];
tokens = parent.nodes;
// Words
} else {
next = pos;
do {
if (code === backslash) {
next += 1;
}
next += 1;
code = value.charCodeAt(next);
} while (
next < max &&
!(
code <= 32 ||
code === singleQuote ||
code === doubleQuote ||
code === comma ||
code === colon ||
code === slash ||
code === openParentheses ||
(code === star &&
parent &&
parent.type === "function" &&
parent.value === "calc") ||
(code === slash &&
parent.type === "function" &&
parent.value === "calc") ||
(code === closeParentheses && balanced)
)
);
token = value.slice(pos, next);
if (openParentheses === code) {
name = token;
} else if (
(uLower === token.charCodeAt(0) || uUpper === token.charCodeAt(0)) &&
plus === token.charCodeAt(1) &&
isUnicodeRange.test(token.slice(2))
) {
tokens.push({
type: "unicode-range",
sourceIndex: pos,
sourceEndIndex: next,
value: token
});
} else {
tokens.push({
type: "word",
sourceIndex: pos,
sourceEndIndex: next,
value: token
});
}
pos = next;
}
}
for (pos = stack.length - 1; pos; pos -= 1) {
stack[pos].unclosed = true;
stack[pos].sourceEndIndex = value.length;
}
return stack[0].nodes;
};
/***/ }),
/***/ 9055:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
let Warning = __webpack_require__(5776)
class Result {
get content() {
return this.css
}
constructor(processor, root, opts) {
this.processor = processor
this.messages = []
this.root = root
this.opts = opts
this.css = undefined
this.map = undefined
}
toString() {
return this.css
}
warn(text, opts = {}) {
if (!opts.plugin) {
if (this.lastPlugin && this.lastPlugin.postcssPlugin) {
opts.plugin = this.lastPlugin.postcssPlugin
}
}
let warning = new Warning(text, opts)
this.messages.push(warning)
return warning
}
warnings() {
return this.messages.filter(i => i.type === 'warning')
}
}
module.exports = Result
Result.default = Result
/***/ }),
/***/ 9434:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
let Container = __webpack_require__(683)
let LazyResult, Processor
class Root extends Container {
constructor(defaults) {
super(defaults)
this.type = 'root'
if (!this.nodes) this.nodes = []
}
normalize(child, sample, type) {
let nodes = super.normalize(child)
if (sample) {
if (type === 'prepend') {
if (this.nodes.length > 1) {
sample.raws.before = this.nodes[1].raws.before
} else {
delete sample.raws.before
}
} else if (this.first !== sample) {
for (let node of nodes) {
node.raws.before = sample.raws.before
}
}
}
return nodes
}
removeChild(child, ignore) {
let index = this.index(child)
if (!ignore && index === 0 && this.nodes.length > 1) {
this.nodes[1].raws.before = this.nodes[index].raws.before
}
return super.removeChild(child)
}
toResult(opts = {}) {
let lazy = new LazyResult(new Processor(), this, opts)
return lazy.stringify()
}
}
Root.registerLazyResult = dependant => {
LazyResult = dependant
}
Root.registerProcessor = dependant => {
Processor = dependant
}
module.exports = Root
Root.default = Root
Container.registerRoot(Root)
/***/ }),
/***/ 9656:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
let Document = __webpack_require__(271)
let LazyResult = __webpack_require__(448)
let NoWorkResult = __webpack_require__(7661)
let Root = __webpack_require__(9434)
class Processor {
constructor(plugins = []) {
this.version = '8.5.3'
this.plugins = this.normalize(plugins)
}
normalize(plugins) {
let normalized = []
for (let i of plugins) {
if (i.postcss === true) {
i = i()
} else if (i.postcss) {
i = i.postcss
}
if (typeof i === 'object' && Array.isArray(i.plugins)) {
normalized = normalized.concat(i.plugins)
} else if (typeof i === 'object' && i.postcssPlugin) {
normalized.push(i)
} else if (typeof i === 'function') {
normalized.push(i)
} else if (typeof i === 'object' && (i.parse || i.stringify)) {
if (false) {}
} else {
throw new Error(i + ' is not a PostCSS plugin')
}
}
return normalized
}
process(css, opts = {}) {
if (
!this.plugins.length &&
!opts.parser &&
!opts.stringifier &&
!opts.syntax
) {
return new NoWorkResult(this, css, opts)
} else {
return new LazyResult(this, css, opts)
}
}
use(plugin) {
this.plugins = this.plugins.concat(this.normalize([plugin]))
return this
}
}
module.exports = Processor
Processor.default = Processor
Root.registerProcessor(Processor)
Document.registerProcessor(Processor)
/***/ }),
/***/ 9681:
/***/ ((module) => {
var characterMap = {
"À": "A",
"Á": "A",
"Â": "A",
"Ã": "A",
"Ä": "A",
"Å": "A",
"Ấ": "A",
"Ắ": "A",
"Ẳ": "A",
"Ẵ": "A",
"Ặ": "A",
"Æ": "AE",
"Ầ": "A",
"Ằ": "A",
"Ȃ": "A",
"Ả": "A",
"Ạ": "A",
"Ẩ": "A",
"Ẫ": "A",
"Ậ": "A",
"Ç": "C",
"Ḉ": "C",
"È": "E",
"É": "E",
"Ê": "E",
"Ë": "E",
"Ế": "E",
"Ḗ": "E",
"Ề": "E",
"Ḕ": "E",
"Ḝ": "E",
"Ȇ": "E",
"Ẻ": "E",
"Ẽ": "E",
"Ẹ": "E",
"Ể": "E",
"Ễ": "E",
"Ệ": "E",
"Ì": "I",
"Í": "I",
"Î": "I",
"Ï": "I",
"Ḯ": "I",
"Ȋ": "I",
"Ỉ": "I",
"Ị": "I",
"Ð": "D",
"Ñ": "N",
"Ò": "O",
"Ó": "O",
"Ô": "O",
"Õ": "O",
"Ö": "O",
"Ø": "O",
"Ố": "O",
"Ṍ": "O",
"Ṓ": "O",
"Ȏ": "O",
"Ỏ": "O",
"Ọ": "O",
"Ổ": "O",
"Ỗ": "O",
"Ộ": "O",
"Ờ": "O",
"Ở": "O",
"Ỡ": "O",
"Ớ": "O",
"Ợ": "O",
"Ù": "U",
"Ú": "U",
"Û": "U",
"Ü": "U",
"Ủ": "U",
"Ụ": "U",
"Ử": "U",
"Ữ": "U",
"Ự": "U",
"Ý": "Y",
"à": "a",
"á": "a",
"â": "a",
"ã": "a",
"ä": "a",
"å": "a",
"ấ": "a",
"ắ": "a",
"ẳ": "a",
"ẵ": "a",
"ặ": "a",
"æ": "ae",
"ầ": "a",
"ằ": "a",
"ȃ": "a",
"ả": "a",
"ạ": "a",
"ẩ": "a",
"ẫ": "a",
"ậ": "a",
"ç": "c",
"ḉ": "c",
"è": "e",
"é": "e",
"ê": "e",
"ë": "e",
"ế": "e",
"ḗ": "e",
"ề": "e",
"ḕ": "e",
"ḝ": "e",
"ȇ": "e",
"ẻ": "e",
"ẽ": "e",
"ẹ": "e",
"ể": "e",
"ễ": "e",
"ệ": "e",
"ì": "i",
"í": "i",
"î": "i",
"ï": "i",
"ḯ": "i",
"ȋ": "i",
"ỉ": "i",
"ị": "i",
"ð": "d",
"ñ": "n",
"ò": "o",
"ó": "o",
"ô": "o",
"õ": "o",
"ö": "o",
"ø": "o",
"ố": "o",
"ṍ": "o",
"ṓ": "o",
"ȏ": "o",
"ỏ": "o",
"ọ": "o",
"ổ": "o",
"ỗ": "o",
"ộ": "o",
"ờ": "o",
"ở": "o",
"ỡ": "o",
"ớ": "o",
"ợ": "o",
"ù": "u",
"ú": "u",
"û": "u",
"ü": "u",
"ủ": "u",
"ụ": "u",
"ử": "u",
"ữ": "u",
"ự": "u",
"ý": "y",
"ÿ": "y",
"Ā": "A",
"ā": "a",
"Ă": "A",
"ă": "a",
"Ą": "A",
"ą": "a",
"Ć": "C",
"ć": "c",
"Ĉ": "C",
"ĉ": "c",
"Ċ": "C",
"ċ": "c",
"Č": "C",
"č": "c",
"C̆": "C",
"c̆": "c",
"Ď": "D",
"ď": "d",
"Đ": "D",
"đ": "d",
"Ē": "E",
"ē": "e",
"Ĕ": "E",
"ĕ": "e",
"Ė": "E",
"ė": "e",
"Ę": "E",
"ę": "e",
"Ě": "E",
"ě": "e",
"Ĝ": "G",
"Ǵ": "G",
"ĝ": "g",
"ǵ": "g",
"Ğ": "G",
"ğ": "g",
"Ġ": "G",
"ġ": "g",
"Ģ": "G",
"ģ": "g",
"Ĥ": "H",
"ĥ": "h",
"Ħ": "H",
"ħ": "h",
"Ḫ": "H",
"ḫ": "h",
"Ĩ": "I",
"ĩ": "i",
"Ī": "I",
"ī": "i",
"Ĭ": "I",
"ĭ": "i",
"Į": "I",
"į": "i",
"İ": "I",
"ı": "i",
"IJ": "IJ",
"ij": "ij",
"Ĵ": "J",
"ĵ": "j",
"Ķ": "K",
"ķ": "k",
"Ḱ": "K",
"ḱ": "k",
"K̆": "K",
"k̆": "k",
"Ĺ": "L",
"ĺ": "l",
"Ļ": "L",
"ļ": "l",
"Ľ": "L",
"ľ": "l",
"Ŀ": "L",
"ŀ": "l",
"Ł": "l",
"ł": "l",
"Ḿ": "M",
"ḿ": "m",
"M̆": "M",
"m̆": "m",
"Ń": "N",
"ń": "n",
"Ņ": "N",
"ņ": "n",
"Ň": "N",
"ň": "n",
"ʼn": "n",
"N̆": "N",
"n̆": "n",
"Ō": "O",
"ō": "o",
"Ŏ": "O",
"ŏ": "o",
"Ő": "O",
"ő": "o",
"Œ": "OE",
"œ": "oe",
"P̆": "P",
"p̆": "p",
"Ŕ": "R",
"ŕ": "r",
"Ŗ": "R",
"ŗ": "r",
"Ř": "R",
"ř": "r",
"R̆": "R",
"r̆": "r",
"Ȓ": "R",
"ȓ": "r",
"Ś": "S",
"ś": "s",
"Ŝ": "S",
"ŝ": "s",
"Ş": "S",
"Ș": "S",
"ș": "s",
"ş": "s",
"Š": "S",
"š": "s",
"Ţ": "T",
"ţ": "t",
"ț": "t",
"Ț": "T",
"Ť": "T",
"ť": "t",
"Ŧ": "T",
"ŧ": "t",
"T̆": "T",
"t̆": "t",
"Ũ": "U",
"ũ": "u",
"Ū": "U",
"ū": "u",
"Ŭ": "U",
"ŭ": "u",
"Ů": "U",
"ů": "u",
"Ű": "U",
"ű": "u",
"Ų": "U",
"ų": "u",
"Ȗ": "U",
"ȗ": "u",
"V̆": "V",
"v̆": "v",
"Ŵ": "W",
"ŵ": "w",
"Ẃ": "W",
"ẃ": "w",
"X̆": "X",
"x̆": "x",
"Ŷ": "Y",
"ŷ": "y",
"Ÿ": "Y",
"Y̆": "Y",
"y̆": "y",
"Ź": "Z",
"ź": "z",
"Ż": "Z",
"ż": "z",
"Ž": "Z",
"ž": "z",
"ſ": "s",
"ƒ": "f",
"Ơ": "O",
"ơ": "o",
"Ư": "U",
"ư": "u",
"Ǎ": "A",
"ǎ": "a",
"Ǐ": "I",
"ǐ": "i",
"Ǒ": "O",
"ǒ": "o",
"Ǔ": "U",
"ǔ": "u",
"Ǖ": "U",
"ǖ": "u",
"Ǘ": "U",
"ǘ": "u",
"Ǚ": "U",
"ǚ": "u",
"Ǜ": "U",
"ǜ": "u",
"Ứ": "U",
"ứ": "u",
"Ṹ": "U",
"ṹ": "u",
"Ǻ": "A",
"ǻ": "a",
"Ǽ": "AE",
"ǽ": "ae",
"Ǿ": "O",
"ǿ": "o",
"Þ": "TH",
"þ": "th",
"Ṕ": "P",
"ṕ": "p",
"Ṥ": "S",
"ṥ": "s",
"X́": "X",
"x́": "x",
"Ѓ": "Г",
"ѓ": "г",
"Ќ": "К",
"ќ": "к",
"A̋": "A",
"a̋": "a",
"E̋": "E",
"e̋": "e",
"I̋": "I",
"i̋": "i",
"Ǹ": "N",
"ǹ": "n",
"Ồ": "O",
"ồ": "o",
"Ṑ": "O",
"ṑ": "o",
"Ừ": "U",
"ừ": "u",
"Ẁ": "W",
"ẁ": "w",
"Ỳ": "Y",
"ỳ": "y",
"Ȁ": "A",
"ȁ": "a",
"Ȅ": "E",
"ȅ": "e",
"Ȉ": "I",
"ȉ": "i",
"Ȍ": "O",
"ȍ": "o",
"Ȑ": "R",
"ȑ": "r",
"Ȕ": "U",
"ȕ": "u",
"B̌": "B",
"b̌": "b",
"Č̣": "C",
"č̣": "c",
"Ê̌": "E",
"ê̌": "e",
"F̌": "F",
"f̌": "f",
"Ǧ": "G",
"ǧ": "g",
"Ȟ": "H",
"ȟ": "h",
"J̌": "J",
"ǰ": "j",
"Ǩ": "K",
"ǩ": "k",
"M̌": "M",
"m̌": "m",
"P̌": "P",
"p̌": "p",
"Q̌": "Q",
"q̌": "q",
"Ř̩": "R",
"ř̩": "r",
"Ṧ": "S",
"ṧ": "s",
"V̌": "V",
"v̌": "v",
"W̌": "W",
"w̌": "w",
"X̌": "X",
"x̌": "x",
"Y̌": "Y",
"y̌": "y",
"A̧": "A",
"a̧": "a",
"B̧": "B",
"b̧": "b",
"Ḑ": "D",
"ḑ": "d",
"Ȩ": "E",
"ȩ": "e",
"Ɛ̧": "E",
"ɛ̧": "e",
"Ḩ": "H",
"ḩ": "h",
"I̧": "I",
"i̧": "i",
"Ɨ̧": "I",
"ɨ̧": "i",
"M̧": "M",
"m̧": "m",
"O̧": "O",
"o̧": "o",
"Q̧": "Q",
"q̧": "q",
"U̧": "U",
"u̧": "u",
"X̧": "X",
"x̧": "x",
"Z̧": "Z",
"z̧": "z",
"й":"и",
"Й":"И",
"ё":"е",
"Ё":"Е",
};
var chars = Object.keys(characterMap).join('|');
var allAccents = new RegExp(chars, 'g');
var firstAccent = new RegExp(chars, '');
function matcher(match) {
return characterMap[match];
}
var removeAccents = function(string) {
return string.replace(allAccents, matcher);
};
var hasAccents = function(string) {
return !!string.match(firstAccent);
};
module.exports = removeAccents;
module.exports.has = hasAccents;
module.exports.remove = removeAccents;
/***/ }),
/***/ 9746:
/***/ (() => {
/* (ignored) */
/***/ }),
/***/ 9977:
/***/ (() => {
/* (ignored) */
/***/ })
/******/ });
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/************************************************************************/
/******/ /* webpack/runtime/compat get default export */
/******/ (() => {
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = (module) => {
/******/ var getter = module && module.__esModule ?
/******/ () => (module['default']) :
/******/ () => (module);
/******/ __webpack_require__.d(getter, { a: getter });
/******/ return getter;
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (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 */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ (() => {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = (exports) => {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ })();
/******/
/************************************************************************/
var __webpack_exports__ = {};
// This entry needs to be wrapped in an IIFE because it needs to be in strict mode.
(() => {
"use strict";
// ESM COMPAT FLAG
__webpack_require__.r(__webpack_exports__);
// EXPORTS
__webpack_require__.d(__webpack_exports__, {
AlignmentControl: () => (/* reexport */ AlignmentControl),
AlignmentToolbar: () => (/* reexport */ AlignmentToolbar),
Autocomplete: () => (/* reexport */ autocomplete),
BlockAlignmentControl: () => (/* reexport */ BlockAlignmentControl),
BlockAlignmentToolbar: () => (/* reexport */ BlockAlignmentToolbar),
BlockBreadcrumb: () => (/* reexport */ block_breadcrumb),
BlockCanvas: () => (/* reexport */ block_canvas),
BlockColorsStyleSelector: () => (/* reexport */ color_style_selector),
BlockContextProvider: () => (/* reexport */ BlockContextProvider),
BlockControls: () => (/* reexport */ block_controls),
BlockEdit: () => (/* reexport */ BlockEdit),
BlockEditorKeyboardShortcuts: () => (/* reexport */ keyboard_shortcuts),
BlockEditorProvider: () => (/* reexport */ components_provider),
BlockFormatControls: () => (/* reexport */ BlockFormatControls),
BlockIcon: () => (/* reexport */ block_icon),
BlockInspector: () => (/* reexport */ block_inspector),
BlockList: () => (/* reexport */ BlockList),
BlockMover: () => (/* reexport */ block_mover),
BlockNavigationDropdown: () => (/* reexport */ dropdown),
BlockPopover: () => (/* reexport */ block_popover),
BlockPreview: () => (/* reexport */ block_preview),
BlockSelectionClearer: () => (/* reexport */ BlockSelectionClearer),
BlockSettingsMenu: () => (/* reexport */ block_settings_menu),
BlockSettingsMenuControls: () => (/* reexport */ block_settings_menu_controls),
BlockStyles: () => (/* reexport */ block_styles),
BlockTitle: () => (/* reexport */ BlockTitle),
BlockToolbar: () => (/* reexport */ BlockToolbar),
BlockTools: () => (/* reexport */ BlockTools),
BlockVerticalAlignmentControl: () => (/* reexport */ BlockVerticalAlignmentControl),
BlockVerticalAlignmentToolbar: () => (/* reexport */ BlockVerticalAlignmentToolbar),
ButtonBlockAppender: () => (/* reexport */ button_block_appender),
ButtonBlockerAppender: () => (/* reexport */ ButtonBlockerAppender),
ColorPalette: () => (/* reexport */ color_palette),
ColorPaletteControl: () => (/* reexport */ ColorPaletteControl),
ContrastChecker: () => (/* reexport */ contrast_checker),
CopyHandler: () => (/* reexport */ CopyHandler),
DefaultBlockAppender: () => (/* reexport */ DefaultBlockAppender),
FontSizePicker: () => (/* reexport */ font_size_picker),
HeadingLevelDropdown: () => (/* reexport */ HeadingLevelDropdown),
HeightControl: () => (/* reexport */ HeightControl),
InnerBlocks: () => (/* reexport */ inner_blocks),
Inserter: () => (/* reexport */ inserter),
InspectorAdvancedControls: () => (/* reexport */ InspectorAdvancedControls),
InspectorControls: () => (/* reexport */ inspector_controls),
JustifyContentControl: () => (/* reexport */ JustifyContentControl),
JustifyToolbar: () => (/* reexport */ JustifyToolbar),
LineHeightControl: () => (/* reexport */ line_height_control),
LinkControl: () => (/* reexport */ link_control),
MediaPlaceholder: () => (/* reexport */ media_placeholder),
MediaReplaceFlow: () => (/* reexport */ media_replace_flow),
MediaUpload: () => (/* reexport */ media_upload),
MediaUploadCheck: () => (/* reexport */ check),
MultiSelectScrollIntoView: () => (/* reexport */ MultiSelectScrollIntoView),
NavigableToolbar: () => (/* reexport */ NavigableToolbar),
ObserveTyping: () => (/* reexport */ observe_typing),
PanelColorSettings: () => (/* reexport */ panel_color_settings),
PlainText: () => (/* reexport */ plain_text),
RecursionProvider: () => (/* reexport */ RecursionProvider),
RichText: () => (/* reexport */ rich_text),
RichTextShortcut: () => (/* reexport */ RichTextShortcut),
RichTextToolbarButton: () => (/* reexport */ RichTextToolbarButton),
SETTINGS_DEFAULTS: () => (/* reexport */ SETTINGS_DEFAULTS),
SkipToSelectedBlock: () => (/* reexport */ SkipToSelectedBlock),
ToolSelector: () => (/* reexport */ tool_selector),
Typewriter: () => (/* reexport */ typewriter),
URLInput: () => (/* reexport */ url_input),
URLInputButton: () => (/* reexport */ url_input_button),
URLPopover: () => (/* reexport */ url_popover),
Warning: () => (/* reexport */ warning),
WritingFlow: () => (/* reexport */ writing_flow),
__experimentalBlockAlignmentMatrixControl: () => (/* reexport */ block_alignment_matrix_control),
__experimentalBlockFullHeightAligmentControl: () => (/* reexport */ block_full_height_alignment_control),
__experimentalBlockPatternSetup: () => (/* reexport */ block_pattern_setup),
__experimentalBlockPatternsList: () => (/* reexport */ block_patterns_list),
__experimentalBlockVariationPicker: () => (/* reexport */ block_variation_picker),
__experimentalBlockVariationTransforms: () => (/* reexport */ block_variation_transforms),
__experimentalBorderRadiusControl: () => (/* reexport */ BorderRadiusControl),
__experimentalColorGradientControl: () => (/* reexport */ control),
__experimentalColorGradientSettingsDropdown: () => (/* reexport */ ColorGradientSettingsDropdown),
__experimentalDateFormatPicker: () => (/* reexport */ DateFormatPicker),
__experimentalDuotoneControl: () => (/* reexport */ duotone_control),
__experimentalFontAppearanceControl: () => (/* reexport */ FontAppearanceControl),
__experimentalFontFamilyControl: () => (/* reexport */ FontFamilyControl),
__experimentalGetBorderClassesAndStyles: () => (/* reexport */ getBorderClassesAndStyles),
__experimentalGetColorClassesAndStyles: () => (/* reexport */ getColorClassesAndStyles),
__experimentalGetElementClassName: () => (/* reexport */ __experimentalGetElementClassName),
__experimentalGetGapCSSValue: () => (/* reexport */ getGapCSSValue),
__experimentalGetGradientClass: () => (/* reexport */ __experimentalGetGradientClass),
__experimentalGetGradientObjectByGradientValue: () => (/* reexport */ __experimentalGetGradientObjectByGradientValue),
__experimentalGetShadowClassesAndStyles: () => (/* reexport */ getShadowClassesAndStyles),
__experimentalGetSpacingClassesAndStyles: () => (/* reexport */ getSpacingClassesAndStyles),
__experimentalImageEditor: () => (/* reexport */ ImageEditor),
__experimentalImageSizeControl: () => (/* reexport */ ImageSizeControl),
__experimentalImageURLInputUI: () => (/* reexport */ ImageURLInputUI),
__experimentalInspectorPopoverHeader: () => (/* reexport */ InspectorPopoverHeader),
__experimentalLetterSpacingControl: () => (/* reexport */ LetterSpacingControl),
__experimentalLibrary: () => (/* reexport */ library),
__experimentalLinkControl: () => (/* reexport */ DeprecatedExperimentalLinkControl),
__experimentalLinkControlSearchInput: () => (/* reexport */ __experimentalLinkControlSearchInput),
__experimentalLinkControlSearchItem: () => (/* reexport */ __experimentalLinkControlSearchItem),
__experimentalLinkControlSearchResults: () => (/* reexport */ __experimentalLinkControlSearchResults),
__experimentalListView: () => (/* reexport */ components_list_view),
__experimentalPanelColorGradientSettings: () => (/* reexport */ panel_color_gradient_settings),
__experimentalPreviewOptions: () => (/* reexport */ PreviewOptions),
__experimentalPublishDateTimePicker: () => (/* reexport */ publish_date_time_picker),
__experimentalRecursionProvider: () => (/* reexport */ DeprecatedExperimentalRecursionProvider),
__experimentalResponsiveBlockControl: () => (/* reexport */ responsive_block_control),
__experimentalSpacingSizesControl: () => (/* reexport */ SpacingSizesControl),
__experimentalTextDecorationControl: () => (/* reexport */ TextDecorationControl),
__experimentalTextTransformControl: () => (/* reexport */ TextTransformControl),
__experimentalUnitControl: () => (/* reexport */ UnitControl),
__experimentalUseBlockOverlayActive: () => (/* reexport */ useBlockOverlayActive),
__experimentalUseBlockPreview: () => (/* reexport */ useBlockPreview),
__experimentalUseBorderProps: () => (/* reexport */ useBorderProps),
__experimentalUseColorProps: () => (/* reexport */ useColorProps),
__experimentalUseCustomSides: () => (/* reexport */ useCustomSides),
__experimentalUseGradient: () => (/* reexport */ __experimentalUseGradient),
__experimentalUseHasRecursion: () => (/* reexport */ DeprecatedExperimentalUseHasRecursion),
__experimentalUseMultipleOriginColorsAndGradients: () => (/* reexport */ useMultipleOriginColorsAndGradients),
__experimentalUseResizeCanvas: () => (/* reexport */ useResizeCanvas),
__experimentalWritingModeControl: () => (/* reexport */ WritingModeControl),
__unstableBlockNameContext: () => (/* reexport */ block_name_context),
__unstableBlockSettingsMenuFirstItem: () => (/* reexport */ block_settings_menu_first_item),
__unstableBlockToolbarLastItem: () => (/* reexport */ block_toolbar_last_item),
__unstableEditorStyles: () => (/* reexport */ editor_styles),
__unstableIframe: () => (/* reexport */ iframe),
__unstableInserterMenuExtension: () => (/* reexport */ inserter_menu_extension),
__unstableRichTextInputEvent: () => (/* reexport */ __unstableRichTextInputEvent),
__unstableUseBlockSelectionClearer: () => (/* reexport */ useBlockSelectionClearer),
__unstableUseClipboardHandler: () => (/* reexport */ __unstableUseClipboardHandler),
__unstableUseMouseMoveTypingReset: () => (/* reexport */ useMouseMoveTypingReset),
__unstableUseTypewriter: () => (/* reexport */ useTypewriter),
__unstableUseTypingObserver: () => (/* reexport */ useTypingObserver),
createCustomColorsHOC: () => (/* reexport */ createCustomColorsHOC),
getColorClassName: () => (/* reexport */ getColorClassName),
getColorObjectByAttributeValues: () => (/* reexport */ getColorObjectByAttributeValues),
getColorObjectByColorValue: () => (/* reexport */ getColorObjectByColorValue),
getComputedFluidTypographyValue: () => (/* reexport */ getComputedFluidTypographyValue),
getCustomValueFromPreset: () => (/* reexport */ getCustomValueFromPreset),
getFontSize: () => (/* reexport */ utils_getFontSize),
getFontSizeClass: () => (/* reexport */ getFontSizeClass),
getFontSizeObjectByValue: () => (/* reexport */ utils_getFontSizeObjectByValue),
getGradientSlugByValue: () => (/* reexport */ getGradientSlugByValue),
getGradientValueBySlug: () => (/* reexport */ getGradientValueBySlug),
getPxFromCssUnit: () => (/* reexport */ get_px_from_css_unit),
getSpacingPresetCssVar: () => (/* reexport */ getSpacingPresetCssVar),
getTypographyClassesAndStyles: () => (/* reexport */ getTypographyClassesAndStyles),
isValueSpacingPreset: () => (/* reexport */ isValueSpacingPreset),
privateApis: () => (/* reexport */ privateApis),
store: () => (/* reexport */ store),
storeConfig: () => (/* reexport */ storeConfig),
transformStyles: () => (/* reexport */ transform_styles),
useBlockBindingsUtils: () => (/* reexport */ useBlockBindingsUtils),
useBlockCommands: () => (/* reexport */ useBlockCommands),
useBlockDisplayInformation: () => (/* reexport */ useBlockDisplayInformation),
useBlockEditContext: () => (/* reexport */ useBlockEditContext),
useBlockEditingMode: () => (/* reexport */ useBlockEditingMode),
useBlockProps: () => (/* reexport */ use_block_props_useBlockProps),
useCachedTruthy: () => (/* reexport */ useCachedTruthy),
useHasRecursion: () => (/* reexport */ useHasRecursion),
useInnerBlocksProps: () => (/* reexport */ useInnerBlocksProps),
useSetting: () => (/* reexport */ useSetting),
useSettings: () => (/* reexport */ use_settings_useSettings),
useStyleOverride: () => (/* reexport */ useStyleOverride),
withColorContext: () => (/* reexport */ with_color_context),
withColors: () => (/* reexport */ withColors),
withFontSizes: () => (/* reexport */ with_font_sizes)
});
// NAMESPACE OBJECT: ./node_modules/@wordpress/block-editor/build-module/store/private-selectors.js
var private_selectors_namespaceObject = {};
__webpack_require__.r(private_selectors_namespaceObject);
__webpack_require__.d(private_selectors_namespaceObject, {
getAllPatterns: () => (getAllPatterns),
getBlockRemovalRules: () => (getBlockRemovalRules),
getBlockSettings: () => (getBlockSettings),
getBlockStyles: () => (getBlockStyles),
getBlockWithoutAttributes: () => (getBlockWithoutAttributes),
getClosestAllowedInsertionPoint: () => (getClosestAllowedInsertionPoint),
getClosestAllowedInsertionPointForPattern: () => (getClosestAllowedInsertionPointForPattern),
getContentLockingParent: () => (getContentLockingParent),
getEnabledBlockParents: () => (getEnabledBlockParents),
getEnabledClientIdsTree: () => (getEnabledClientIdsTree),
getExpandedBlock: () => (getExpandedBlock),
getInserterMediaCategories: () => (getInserterMediaCategories),
getInsertionPoint: () => (getInsertionPoint),
getLastFocus: () => (getLastFocus),
getLastInsertedBlocksClientIds: () => (getLastInsertedBlocksClientIds),
getOpenedBlockSettingsMenu: () => (getOpenedBlockSettingsMenu),
getParentSectionBlock: () => (getParentSectionBlock),
getPatternBySlug: () => (getPatternBySlug),
getRegisteredInserterMediaCategories: () => (getRegisteredInserterMediaCategories),
getRemovalPromptData: () => (getRemovalPromptData),
getReusableBlocks: () => (getReusableBlocks),
getSectionRootClientId: () => (getSectionRootClientId),
getStyleOverrides: () => (getStyleOverrides),
getTemporarilyEditingAsBlocks: () => (getTemporarilyEditingAsBlocks),
getTemporarilyEditingFocusModeToRevert: () => (getTemporarilyEditingFocusModeToRevert),
getZoomLevel: () => (getZoomLevel),
hasAllowedPatterns: () => (hasAllowedPatterns),
isBlockInterfaceHidden: () => (private_selectors_isBlockInterfaceHidden),
isBlockSubtreeDisabled: () => (isBlockSubtreeDisabled),
isDragging: () => (private_selectors_isDragging),
isSectionBlock: () => (isSectionBlock),
isZoomOut: () => (isZoomOut)
});
// NAMESPACE OBJECT: ./node_modules/@wordpress/block-editor/build-module/store/selectors.js
var selectors_namespaceObject = {};
__webpack_require__.r(selectors_namespaceObject);
__webpack_require__.d(selectors_namespaceObject, {
__experimentalGetActiveBlockIdByBlockNames: () => (__experimentalGetActiveBlockIdByBlockNames),
__experimentalGetAllowedBlocks: () => (__experimentalGetAllowedBlocks),
__experimentalGetAllowedPatterns: () => (__experimentalGetAllowedPatterns),
__experimentalGetBlockListSettingsForBlocks: () => (__experimentalGetBlockListSettingsForBlocks),
__experimentalGetDirectInsertBlock: () => (__experimentalGetDirectInsertBlock),
__experimentalGetGlobalBlocksByName: () => (__experimentalGetGlobalBlocksByName),
__experimentalGetLastBlockAttributeChanges: () => (__experimentalGetLastBlockAttributeChanges),
__experimentalGetParsedPattern: () => (__experimentalGetParsedPattern),
__experimentalGetPatternTransformItems: () => (__experimentalGetPatternTransformItems),
__experimentalGetPatternsByBlockTypes: () => (__experimentalGetPatternsByBlockTypes),
__experimentalGetReusableBlockTitle: () => (__experimentalGetReusableBlockTitle),
__unstableGetBlockWithoutInnerBlocks: () => (__unstableGetBlockWithoutInnerBlocks),
__unstableGetClientIdWithClientIdsTree: () => (__unstableGetClientIdWithClientIdsTree),
__unstableGetClientIdsTree: () => (__unstableGetClientIdsTree),
__unstableGetContentLockingParent: () => (__unstableGetContentLockingParent),
__unstableGetEditorMode: () => (__unstableGetEditorMode),
__unstableGetSelectedBlocksWithPartialSelection: () => (__unstableGetSelectedBlocksWithPartialSelection),
__unstableGetTemporarilyEditingAsBlocks: () => (__unstableGetTemporarilyEditingAsBlocks),
__unstableGetTemporarilyEditingFocusModeToRevert: () => (__unstableGetTemporarilyEditingFocusModeToRevert),
__unstableGetVisibleBlocks: () => (__unstableGetVisibleBlocks),
__unstableHasActiveBlockOverlayActive: () => (__unstableHasActiveBlockOverlayActive),
__unstableIsFullySelected: () => (__unstableIsFullySelected),
__unstableIsLastBlockChangeIgnored: () => (__unstableIsLastBlockChangeIgnored),
__unstableIsSelectionCollapsed: () => (__unstableIsSelectionCollapsed),
__unstableIsSelectionMergeable: () => (__unstableIsSelectionMergeable),
__unstableIsWithinBlockOverlay: () => (__unstableIsWithinBlockOverlay),
__unstableSelectionHasUnmergeableBlock: () => (__unstableSelectionHasUnmergeableBlock),
areInnerBlocksControlled: () => (areInnerBlocksControlled),
canEditBlock: () => (canEditBlock),
canInsertBlockType: () => (canInsertBlockType),
canInsertBlocks: () => (canInsertBlocks),
canLockBlockType: () => (canLockBlockType),
canMoveBlock: () => (canMoveBlock),
canMoveBlocks: () => (canMoveBlocks),
canRemoveBlock: () => (canRemoveBlock),
canRemoveBlocks: () => (canRemoveBlocks),
didAutomaticChange: () => (didAutomaticChange),
getAdjacentBlockClientId: () => (getAdjacentBlockClientId),
getAllowedBlocks: () => (getAllowedBlocks),
getBlock: () => (getBlock),
getBlockAttributes: () => (getBlockAttributes),
getBlockCount: () => (getBlockCount),
getBlockEditingMode: () => (getBlockEditingMode),
getBlockHierarchyRootClientId: () => (getBlockHierarchyRootClientId),
getBlockIndex: () => (getBlockIndex),
getBlockInsertionPoint: () => (getBlockInsertionPoint),
getBlockListSettings: () => (getBlockListSettings),
getBlockMode: () => (getBlockMode),
getBlockName: () => (getBlockName),
getBlockNamesByClientId: () => (getBlockNamesByClientId),
getBlockOrder: () => (getBlockOrder),
getBlockParents: () => (getBlockParents),
getBlockParentsByBlockName: () => (getBlockParentsByBlockName),
getBlockRootClientId: () => (getBlockRootClientId),
getBlockSelectionEnd: () => (getBlockSelectionEnd),
getBlockSelectionStart: () => (getBlockSelectionStart),
getBlockTransformItems: () => (getBlockTransformItems),
getBlocks: () => (getBlocks),
getBlocksByClientId: () => (getBlocksByClientId),
getBlocksByName: () => (getBlocksByName),
getClientIdsOfDescendants: () => (getClientIdsOfDescendants),
getClientIdsWithDescendants: () => (getClientIdsWithDescendants),
getDirectInsertBlock: () => (getDirectInsertBlock),
getDraggedBlockClientIds: () => (getDraggedBlockClientIds),
getFirstMultiSelectedBlockClientId: () => (getFirstMultiSelectedBlockClientId),
getGlobalBlockCount: () => (getGlobalBlockCount),
getHoveredBlockClientId: () => (getHoveredBlockClientId),
getInserterItems: () => (getInserterItems),
getLastMultiSelectedBlockClientId: () => (getLastMultiSelectedBlockClientId),
getLowestCommonAncestorWithSelectedBlock: () => (getLowestCommonAncestorWithSelectedBlock),
getMultiSelectedBlockClientIds: () => (getMultiSelectedBlockClientIds),
getMultiSelectedBlocks: () => (getMultiSelectedBlocks),
getMultiSelectedBlocksEndClientId: () => (getMultiSelectedBlocksEndClientId),
getMultiSelectedBlocksStartClientId: () => (getMultiSelectedBlocksStartClientId),
getNextBlockClientId: () => (getNextBlockClientId),
getPatternsByBlockTypes: () => (getPatternsByBlockTypes),
getPreviousBlockClientId: () => (getPreviousBlockClientId),
getSelectedBlock: () => (getSelectedBlock),
getSelectedBlockClientId: () => (getSelectedBlockClientId),
getSelectedBlockClientIds: () => (getSelectedBlockClientIds),
getSelectedBlockCount: () => (getSelectedBlockCount),
getSelectedBlocksInitialCaretPosition: () => (getSelectedBlocksInitialCaretPosition),
getSelectionEnd: () => (getSelectionEnd),
getSelectionStart: () => (getSelectionStart),
getSettings: () => (getSettings),
getTemplate: () => (getTemplate),
getTemplateLock: () => (getTemplateLock),
hasBlockMovingClientId: () => (hasBlockMovingClientId),
hasDraggedInnerBlock: () => (hasDraggedInnerBlock),
hasInserterItems: () => (hasInserterItems),
hasMultiSelection: () => (hasMultiSelection),
hasSelectedBlock: () => (hasSelectedBlock),
hasSelectedInnerBlock: () => (hasSelectedInnerBlock),
isAncestorBeingDragged: () => (isAncestorBeingDragged),
isAncestorMultiSelected: () => (isAncestorMultiSelected),
isBlockBeingDragged: () => (isBlockBeingDragged),
isBlockHighlighted: () => (isBlockHighlighted),
isBlockInsertionPointVisible: () => (isBlockInsertionPointVisible),
isBlockMultiSelected: () => (isBlockMultiSelected),
isBlockSelected: () => (isBlockSelected),
isBlockValid: () => (isBlockValid),
isBlockVisible: () => (isBlockVisible),
isBlockWithinSelection: () => (isBlockWithinSelection),
isCaretWithinFormattedText: () => (isCaretWithinFormattedText),
isDraggingBlocks: () => (isDraggingBlocks),
isFirstMultiSelectedBlock: () => (isFirstMultiSelectedBlock),
isGroupable: () => (isGroupable),
isLastBlockChangePersistent: () => (isLastBlockChangePersistent),
isMultiSelecting: () => (selectors_isMultiSelecting),
isNavigationMode: () => (isNavigationMode),
isSelectionEnabled: () => (selectors_isSelectionEnabled),
isTyping: () => (selectors_isTyping),
isUngroupable: () => (isUngroupable),
isValidTemplate: () => (isValidTemplate),
wasBlockJustInserted: () => (wasBlockJustInserted)
});
// NAMESPACE OBJECT: ./node_modules/@wordpress/block-editor/build-module/store/private-actions.js
var private_actions_namespaceObject = {};
__webpack_require__.r(private_actions_namespaceObject);
__webpack_require__.d(private_actions_namespaceObject, {
__experimentalUpdateSettings: () => (__experimentalUpdateSettings),
clearBlockRemovalPrompt: () => (clearBlockRemovalPrompt),
deleteStyleOverride: () => (deleteStyleOverride),
ensureDefaultBlock: () => (ensureDefaultBlock),
expandBlock: () => (expandBlock),
hideBlockInterface: () => (hideBlockInterface),
modifyContentLockBlock: () => (modifyContentLockBlock),
privateRemoveBlocks: () => (privateRemoveBlocks),
resetZoomLevel: () => (resetZoomLevel),
setBlockRemovalRules: () => (setBlockRemovalRules),
setInsertionPoint: () => (setInsertionPoint),
setLastFocus: () => (setLastFocus),
setOpenedBlockSettingsMenu: () => (setOpenedBlockSettingsMenu),
setStyleOverride: () => (setStyleOverride),
setZoomLevel: () => (setZoomLevel),
showBlockInterface: () => (showBlockInterface),
startDragging: () => (startDragging),
stopDragging: () => (stopDragging),
stopEditingAsBlocks: () => (stopEditingAsBlocks)
});
// NAMESPACE OBJECT: ./node_modules/@wordpress/block-editor/build-module/store/actions.js
var actions_namespaceObject = {};
__webpack_require__.r(actions_namespaceObject);
__webpack_require__.d(actions_namespaceObject, {
__unstableDeleteSelection: () => (__unstableDeleteSelection),
__unstableExpandSelection: () => (__unstableExpandSelection),
__unstableMarkAutomaticChange: () => (__unstableMarkAutomaticChange),
__unstableMarkLastChangeAsPersistent: () => (__unstableMarkLastChangeAsPersistent),
__unstableMarkNextChangeAsNotPersistent: () => (__unstableMarkNextChangeAsNotPersistent),
__unstableSaveReusableBlock: () => (__unstableSaveReusableBlock),
__unstableSetEditorMode: () => (__unstableSetEditorMode),
__unstableSetTemporarilyEditingAsBlocks: () => (__unstableSetTemporarilyEditingAsBlocks),
__unstableSplitSelection: () => (__unstableSplitSelection),
clearSelectedBlock: () => (clearSelectedBlock),
duplicateBlocks: () => (duplicateBlocks),
enterFormattedText: () => (enterFormattedText),
exitFormattedText: () => (exitFormattedText),
flashBlock: () => (flashBlock),
hideInsertionPoint: () => (hideInsertionPoint),
hoverBlock: () => (hoverBlock),
insertAfterBlock: () => (insertAfterBlock),
insertBeforeBlock: () => (insertBeforeBlock),
insertBlock: () => (insertBlock),
insertBlocks: () => (insertBlocks),
insertDefaultBlock: () => (insertDefaultBlock),
mergeBlocks: () => (mergeBlocks),
moveBlockToPosition: () => (moveBlockToPosition),
moveBlocksDown: () => (moveBlocksDown),
moveBlocksToPosition: () => (moveBlocksToPosition),
moveBlocksUp: () => (moveBlocksUp),
multiSelect: () => (multiSelect),
receiveBlocks: () => (receiveBlocks),
registerInserterMediaCategory: () => (registerInserterMediaCategory),
removeBlock: () => (removeBlock),
removeBlocks: () => (removeBlocks),
replaceBlock: () => (replaceBlock),
replaceBlocks: () => (replaceBlocks),
replaceInnerBlocks: () => (replaceInnerBlocks),
resetBlocks: () => (resetBlocks),
resetSelection: () => (resetSelection),
selectBlock: () => (selectBlock),
selectNextBlock: () => (selectNextBlock),
selectPreviousBlock: () => (selectPreviousBlock),
selectionChange: () => (selectionChange),
setBlockEditingMode: () => (setBlockEditingMode),
setBlockMovingClientId: () => (setBlockMovingClientId),
setBlockVisibility: () => (setBlockVisibility),
setHasControlledInnerBlocks: () => (setHasControlledInnerBlocks),
setNavigationMode: () => (setNavigationMode),
setTemplateValidity: () => (setTemplateValidity),
showInsertionPoint: () => (showInsertionPoint),
startDraggingBlocks: () => (startDraggingBlocks),
startMultiSelect: () => (startMultiSelect),
startTyping: () => (startTyping),
stopDraggingBlocks: () => (stopDraggingBlocks),
stopMultiSelect: () => (stopMultiSelect),
stopTyping: () => (stopTyping),
synchronizeTemplate: () => (synchronizeTemplate),
toggleBlockHighlight: () => (toggleBlockHighlight),
toggleBlockMode: () => (toggleBlockMode),
toggleSelection: () => (toggleSelection),
unsetBlockEditingMode: () => (unsetBlockEditingMode),
updateBlock: () => (updateBlock),
updateBlockAttributes: () => (updateBlockAttributes),
updateBlockListSettings: () => (updateBlockListSettings),
updateSettings: () => (updateSettings),
validateBlocksToTemplate: () => (validateBlocksToTemplate)
});
// NAMESPACE OBJECT: ./node_modules/@wordpress/upload-media/build-module/store/selectors.js
var store_selectors_namespaceObject = {};
__webpack_require__.r(store_selectors_namespaceObject);
__webpack_require__.d(store_selectors_namespaceObject, {
getItems: () => (getItems),
getSettings: () => (selectors_getSettings),
isUploading: () => (isUploading),
isUploadingById: () => (isUploadingById),
isUploadingByUrl: () => (isUploadingByUrl)
});
// NAMESPACE OBJECT: ./node_modules/@wordpress/upload-media/build-module/store/private-selectors.js
var store_private_selectors_namespaceObject = {};
__webpack_require__.r(store_private_selectors_namespaceObject);
__webpack_require__.d(store_private_selectors_namespaceObject, {
getAllItems: () => (getAllItems),
getBlobUrls: () => (getBlobUrls),
getItem: () => (getItem),
getPausedUploadForPost: () => (getPausedUploadForPost),
isBatchUploaded: () => (isBatchUploaded),
isPaused: () => (isPaused),
isUploadingToPost: () => (isUploadingToPost)
});
// NAMESPACE OBJECT: ./node_modules/@wordpress/upload-media/build-module/store/actions.js
var store_actions_namespaceObject = {};
__webpack_require__.r(store_actions_namespaceObject);
__webpack_require__.d(store_actions_namespaceObject, {
addItems: () => (addItems),
cancelItem: () => (cancelItem)
});
// NAMESPACE OBJECT: ./node_modules/@wordpress/upload-media/build-module/store/private-actions.js
var store_private_actions_namespaceObject = {};
__webpack_require__.r(store_private_actions_namespaceObject);
__webpack_require__.d(store_private_actions_namespaceObject, {
addItem: () => (addItem),
finishOperation: () => (finishOperation),
pauseQueue: () => (pauseQueue),
prepareItem: () => (prepareItem),
processItem: () => (processItem),
removeItem: () => (removeItem),
resumeQueue: () => (resumeQueue),
revokeBlobUrls: () => (revokeBlobUrls),
updateSettings: () => (private_actions_updateSettings),
uploadItem: () => (uploadItem)
});
// NAMESPACE OBJECT: ./node_modules/@wordpress/block-editor/build-module/components/global-styles/index.js
var global_styles_namespaceObject = {};
__webpack_require__.r(global_styles_namespaceObject);
__webpack_require__.d(global_styles_namespaceObject, {
AdvancedPanel: () => (AdvancedPanel),
BackgroundPanel: () => (background_panel_BackgroundImagePanel),
BorderPanel: () => (BorderPanel),
ColorPanel: () => (ColorPanel),
DimensionsPanel: () => (DimensionsPanel),
FiltersPanel: () => (FiltersPanel),
GlobalStylesContext: () => (GlobalStylesContext),
ImageSettingsPanel: () => (ImageSettingsPanel),
TypographyPanel: () => (TypographyPanel),
areGlobalStyleConfigsEqual: () => (areGlobalStyleConfigsEqual),
getBlockCSSSelector: () => (getBlockCSSSelector),
getBlockSelectors: () => (getBlockSelectors),
getGlobalStylesChanges: () => (getGlobalStylesChanges),
getLayoutStyles: () => (getLayoutStyles),
toStyles: () => (toStyles),
useGlobalSetting: () => (useGlobalSetting),
useGlobalStyle: () => (useGlobalStyle),
useGlobalStylesOutput: () => (useGlobalStylesOutput),
useGlobalStylesOutputWithConfig: () => (useGlobalStylesOutputWithConfig),
useGlobalStylesReset: () => (useGlobalStylesReset),
useHasBackgroundPanel: () => (useHasBackgroundPanel),
useHasBorderPanel: () => (useHasBorderPanel),
useHasBorderPanelControls: () => (useHasBorderPanelControls),
useHasColorPanel: () => (useHasColorPanel),
useHasDimensionsPanel: () => (useHasDimensionsPanel),
useHasFiltersPanel: () => (useHasFiltersPanel),
useHasImageSettingsPanel: () => (useHasImageSettingsPanel),
useHasTypographyPanel: () => (useHasTypographyPanel),
useSettingsForBlockElement: () => (useSettingsForBlockElement)
});
;// external ["wp","blocks"]
const external_wp_blocks_namespaceObject = window["wp"]["blocks"];
;// external ["wp","element"]
const external_wp_element_namespaceObject = window["wp"]["element"];
;// external ["wp","data"]
const external_wp_data_namespaceObject = window["wp"]["data"];
;// external ["wp","compose"]
const external_wp_compose_namespaceObject = window["wp"]["compose"];
;// external ["wp","hooks"]
const external_wp_hooks_namespaceObject = window["wp"]["hooks"];
;// ./node_modules/@wordpress/block-editor/build-module/components/block-edit/context.js
/**
* WordPress dependencies
*/
const mayDisplayControlsKey = Symbol('mayDisplayControls');
const mayDisplayParentControlsKey = Symbol('mayDisplayParentControls');
const blockEditingModeKey = Symbol('blockEditingMode');
const blockBindingsKey = Symbol('blockBindings');
const isPreviewModeKey = Symbol('isPreviewMode');
const DEFAULT_BLOCK_EDIT_CONTEXT = {
name: '',
isSelected: false
};
const Context = (0,external_wp_element_namespaceObject.createContext)(DEFAULT_BLOCK_EDIT_CONTEXT);
const {
Provider
} = Context;
/**
* A hook that returns the block edit context.
*
* @return {Object} Block edit context
*/
function useBlockEditContext() {
return (0,external_wp_element_namespaceObject.useContext)(Context);
}
;// external ["wp","deprecated"]
const external_wp_deprecated_namespaceObject = window["wp"]["deprecated"];
var external_wp_deprecated_default = /*#__PURE__*/__webpack_require__.n(external_wp_deprecated_namespaceObject);
// EXTERNAL MODULE: ./node_modules/fast-deep-equal/es6/index.js
var es6 = __webpack_require__(7734);
var es6_default = /*#__PURE__*/__webpack_require__.n(es6);
;// external ["wp","i18n"]
const external_wp_i18n_namespaceObject = window["wp"]["i18n"];
;// ./node_modules/@wordpress/block-editor/build-module/store/defaults.js
/**
* WordPress dependencies
*/
const PREFERENCES_DEFAULTS = {
insertUsage: {}
};
/**
* The default editor settings
*
* @typedef {Object} SETTINGS_DEFAULT
* @property {boolean} alignWide Enable/Disable Wide/Full Alignments
* @property {boolean} supportsLayout Enable/disable layouts support in container blocks.
* @property {boolean} imageEditing Image Editing settings set to false to disable.
* @property {Array} imageSizes Available image sizes
* @property {number} maxWidth Max width to constraint resizing
* @property {boolean|Array} allowedBlockTypes Allowed block types
* @property {boolean} hasFixedToolbar Whether or not the editor toolbar is fixed
* @property {boolean} distractionFree Whether or not the editor UI is distraction free
* @property {boolean} focusMode Whether the focus mode is enabled or not
* @property {Array} styles Editor Styles
* @property {boolean} keepCaretInsideBlock Whether caret should move between blocks in edit mode
* @property {string} bodyPlaceholder Empty post placeholder
* @property {string} titlePlaceholder Empty title placeholder
* @property {boolean} canLockBlocks Whether the user can manage Block Lock state
* @property {boolean} codeEditingEnabled Whether or not the user can switch to the code editor
* @property {boolean} generateAnchors Enable/Disable auto anchor generation for Heading blocks
* @property {boolean} enableOpenverseMediaCategory Enable/Disable the Openverse media category in the inserter.
* @property {boolean} clearBlockSelection Whether the block editor should clear selection on mousedown when a block is not clicked.
* @property {boolean} __experimentalCanUserUseUnfilteredHTML Whether the user should be able to use unfiltered HTML or the HTML should be filtered e.g., to remove elements considered insecure like iframes.
* @property {boolean} __experimentalBlockDirectory Whether the user has enabled the Block Directory
* @property {Array} __experimentalBlockPatterns Array of objects representing the block patterns
* @property {Array} __experimentalBlockPatternCategories Array of objects representing the block pattern categories
*/
const SETTINGS_DEFAULTS = {
alignWide: false,
supportsLayout: true,
// colors setting is not used anymore now defaults are passed from theme.json on the server and core has its own defaults.
// The setting is only kept for backward compatibility purposes.
colors: [{
name: (0,external_wp_i18n_namespaceObject.__)('Black'),
slug: 'black',
color: '#000000'
}, {
name: (0,external_wp_i18n_namespaceObject.__)('Cyan bluish gray'),
slug: 'cyan-bluish-gray',
color: '#abb8c3'
}, {
name: (0,external_wp_i18n_namespaceObject.__)('White'),
slug: 'white',
color: '#ffffff'
}, {
name: (0,external_wp_i18n_namespaceObject.__)('Pale pink'),
slug: 'pale-pink',
color: '#f78da7'
}, {
name: (0,external_wp_i18n_namespaceObject.__)('Vivid red'),
slug: 'vivid-red',
color: '#cf2e2e'
}, {
name: (0,external_wp_i18n_namespaceObject.__)('Luminous vivid orange'),
slug: 'luminous-vivid-orange',
color: '#ff6900'
}, {
name: (0,external_wp_i18n_namespaceObject.__)('Luminous vivid amber'),
slug: 'luminous-vivid-amber',
color: '#fcb900'
}, {
name: (0,external_wp_i18n_namespaceObject.__)('Light green cyan'),
slug: 'light-green-cyan',
color: '#7bdcb5'
}, {
name: (0,external_wp_i18n_namespaceObject.__)('Vivid green cyan'),
slug: 'vivid-green-cyan',
color: '#00d084'
}, {
name: (0,external_wp_i18n_namespaceObject.__)('Pale cyan blue'),
slug: 'pale-cyan-blue',
color: '#8ed1fc'
}, {
name: (0,external_wp_i18n_namespaceObject.__)('Vivid cyan blue'),
slug: 'vivid-cyan-blue',
color: '#0693e3'
}, {
name: (0,external_wp_i18n_namespaceObject.__)('Vivid purple'),
slug: 'vivid-purple',
color: '#9b51e0'
}],
// fontSizes setting is not used anymore now defaults are passed from theme.json on the server and core has its own defaults.
// The setting is only kept for backward compatibility purposes.
fontSizes: [{
name: (0,external_wp_i18n_namespaceObject._x)('Small', 'font size name'),
size: 13,
slug: 'small'
}, {
name: (0,external_wp_i18n_namespaceObject._x)('Normal', 'font size name'),
size: 16,
slug: 'normal'
}, {
name: (0,external_wp_i18n_namespaceObject._x)('Medium', 'font size name'),
size: 20,
slug: 'medium'
}, {
name: (0,external_wp_i18n_namespaceObject._x)('Large', 'font size name'),
size: 36,
slug: 'large'
}, {
name: (0,external_wp_i18n_namespaceObject._x)('Huge', 'font size name'),
size: 42,
slug: 'huge'
}],
// Image default size slug.
imageDefaultSize: 'large',
imageSizes: [{
slug: 'thumbnail',
name: (0,external_wp_i18n_namespaceObject.__)('Thumbnail')
}, {
slug: 'medium',
name: (0,external_wp_i18n_namespaceObject.__)('Medium')
}, {
slug: 'large',
name: (0,external_wp_i18n_namespaceObject.__)('Large')
}, {
slug: 'full',
name: (0,external_wp_i18n_namespaceObject.__)('Full Size')
}],
// Allow plugin to disable Image Editor if need be.
imageEditing: true,
// This is current max width of the block inner area
// It's used to constraint image resizing and this value could be overridden later by themes
maxWidth: 580,
// Allowed block types for the editor, defaulting to true (all supported).
allowedBlockTypes: true,
// Maximum upload size in bytes allowed for the site.
maxUploadFileSize: 0,
// List of allowed mime types and file extensions.
allowedMimeTypes: null,
// Allows to disable block locking interface.
canLockBlocks: true,
// Allows to disable Openverse media category in the inserter.
enableOpenverseMediaCategory: true,
clearBlockSelection: true,
__experimentalCanUserUseUnfilteredHTML: false,
__experimentalBlockDirectory: false,
__mobileEnablePageTemplates: false,
__experimentalBlockPatterns: [],
__experimentalBlockPatternCategories: [],
isPreviewMode: false,
// These settings will be completely revamped in the future.
// The goal is to evolve this into an API which will instruct
// the block inspector to animate transitions between what it
// displays based on the relationship between the selected block
// and its parent, and only enable it if the parent is controlling
// its children blocks.
blockInspectorAnimation: {
animationParent: 'core/navigation',
'core/navigation': {
enterDirection: 'leftToRight'
},
'core/navigation-submenu': {
enterDirection: 'rightToLeft'
},
'core/navigation-link': {
enterDirection: 'rightToLeft'
},
'core/search': {
enterDirection: 'rightToLeft'
},
'core/social-links': {
enterDirection: 'rightToLeft'
},
'core/page-list': {
enterDirection: 'rightToLeft'
},
'core/spacer': {
enterDirection: 'rightToLeft'
},
'core/home-link': {
enterDirection: 'rightToLeft'
},
'core/site-title': {
enterDirection: 'rightToLeft'
},
'core/site-logo': {
enterDirection: 'rightToLeft'
}
},
generateAnchors: false,
// gradients setting is not used anymore now defaults are passed from theme.json on the server and core has its own defaults.
// The setting is only kept for backward compatibility purposes.
gradients: [{
name: (0,external_wp_i18n_namespaceObject.__)('Vivid cyan blue to vivid purple'),
gradient: 'linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)',
slug: 'vivid-cyan-blue-to-vivid-purple'
}, {
name: (0,external_wp_i18n_namespaceObject.__)('Light green cyan to vivid green cyan'),
gradient: 'linear-gradient(135deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%)',
slug: 'light-green-cyan-to-vivid-green-cyan'
}, {
name: (0,external_wp_i18n_namespaceObject.__)('Luminous vivid amber to luminous vivid orange'),
gradient: 'linear-gradient(135deg,rgba(252,185,0,1) 0%,rgba(255,105,0,1) 100%)',
slug: 'luminous-vivid-amber-to-luminous-vivid-orange'
}, {
name: (0,external_wp_i18n_namespaceObject.__)('Luminous vivid orange to vivid red'),
gradient: 'linear-gradient(135deg,rgba(255,105,0,1) 0%,rgb(207,46,46) 100%)',
slug: 'luminous-vivid-orange-to-vivid-red'
}, {
name: (0,external_wp_i18n_namespaceObject.__)('Very light gray to cyan bluish gray'),
gradient: 'linear-gradient(135deg,rgb(238,238,238) 0%,rgb(169,184,195) 100%)',
slug: 'very-light-gray-to-cyan-bluish-gray'
}, {
name: (0,external_wp_i18n_namespaceObject.__)('Cool to warm spectrum'),
gradient: 'linear-gradient(135deg,rgb(74,234,220) 0%,rgb(151,120,209) 20%,rgb(207,42,186) 40%,rgb(238,44,130) 60%,rgb(251,105,98) 80%,rgb(254,248,76) 100%)',
slug: 'cool-to-warm-spectrum'
}, {
name: (0,external_wp_i18n_namespaceObject.__)('Blush light purple'),
gradient: 'linear-gradient(135deg,rgb(255,206,236) 0%,rgb(152,150,240) 100%)',
slug: 'blush-light-purple'
}, {
name: (0,external_wp_i18n_namespaceObject.__)('Blush bordeaux'),
gradient: 'linear-gradient(135deg,rgb(254,205,165) 0%,rgb(254,45,45) 50%,rgb(107,0,62) 100%)',
slug: 'blush-bordeaux'
}, {
name: (0,external_wp_i18n_namespaceObject.__)('Luminous dusk'),
gradient: 'linear-gradient(135deg,rgb(255,203,112) 0%,rgb(199,81,192) 50%,rgb(65,88,208) 100%)',
slug: 'luminous-dusk'
}, {
name: (0,external_wp_i18n_namespaceObject.__)('Pale ocean'),
gradient: 'linear-gradient(135deg,rgb(255,245,203) 0%,rgb(182,227,212) 50%,rgb(51,167,181) 100%)',
slug: 'pale-ocean'
}, {
name: (0,external_wp_i18n_namespaceObject.__)('Electric grass'),
gradient: 'linear-gradient(135deg,rgb(202,248,128) 0%,rgb(113,206,126) 100%)',
slug: 'electric-grass'
}, {
name: (0,external_wp_i18n_namespaceObject.__)('Midnight'),
gradient: 'linear-gradient(135deg,rgb(2,3,129) 0%,rgb(40,116,252) 100%)',
slug: 'midnight'
}],
__unstableResolvedAssets: {
styles: [],
scripts: []
}
};
;// ./node_modules/@wordpress/block-editor/build-module/store/array.js
/**
* Insert one or multiple elements into a given position of an array.
*
* @param {Array} array Source array.
* @param {*} elements Elements to insert.
* @param {number} index Insert Position.
*
* @return {Array} Result.
*/
function insertAt(array, elements, index) {
return [...array.slice(0, index), ...(Array.isArray(elements) ? elements : [elements]), ...array.slice(index)];
}
/**
* Moves an element in an array.
*
* @param {Array} array Source array.
* @param {number} from Source index.
* @param {number} to Destination index.
* @param {number} count Number of elements to move.
*
* @return {Array} Result.
*/
function moveTo(array, from, to, count = 1) {
const withoutMovedElements = [...array];
withoutMovedElements.splice(from, count);
return insertAt(withoutMovedElements, array.slice(from, from + count), to);
}
;// ./node_modules/@wordpress/block-editor/build-module/store/private-keys.js
const globalStylesDataKey = Symbol('globalStylesDataKey');
const globalStylesLinksDataKey = Symbol('globalStylesLinks');
const selectBlockPatternsKey = Symbol('selectBlockPatternsKey');
const reusableBlocksSelectKey = Symbol('reusableBlocksSelect');
const sectionRootClientIdKey = Symbol('sectionRootClientIdKey');
;// external ["wp","privateApis"]
const external_wp_privateApis_namespaceObject = window["wp"]["privateApis"];
;// ./node_modules/@wordpress/block-editor/build-module/lock-unlock.js
/**
* WordPress dependencies
*/
const {
lock,
unlock
} = (0,external_wp_privateApis_namespaceObject.__dangerousOptInToUnstableAPIsOnlyForCoreModules)('I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.', '@wordpress/block-editor');
;// ./node_modules/@wordpress/block-editor/build-module/store/reducer.js
/**
* External dependencies
*/
/**
* WordPress dependencies
*/
/**
* Internal dependencies
*/
const {
isContentBlock
} = unlock(external_wp_blocks_namespaceObject.privateApis);
const identity = x => x;
/**
* Given an array of blocks, returns an object where each key is a nesting
* context, the value of which is an array of block client IDs existing within
* that nesting context.
*
* @param {Array} blocks Blocks to map.
* @param {?string} rootClientId Assumed root client ID.
*
* @return {Object} Block order map object.
*/
function mapBlockOrder(blocks, rootClientId = '') {
const result = new Map();
const current = [];
result.set(rootClientId, current);
blocks.forEach(block => {
const {
clientId,
innerBlocks
} = block;
current.push(clientId);
mapBlockOrder(innerBlocks, clientId).forEach((order, subClientId) => {
result.set(subClientId, order);
});
});
return result;
}
/**
* Given an array of blocks, returns an object where each key contains
* the clientId of the block and the value is the parent of the block.
*
* @param {Array} blocks Blocks to map.
* @param {?string} rootClientId Assumed root client ID.
*
* @return {Object} Block order map object.
*/
function mapBlockParents(blocks, rootClientId = '') {
const result = [];
const stack = [[rootClientId, blocks]];
while (stack.length) {
const [parent, currentBlocks] = stack.shift();
currentBlocks.forEach(({
innerBlocks,
...block
}) => {
result.push([block.clientId, parent]);
if (innerBlocks?.length) {
stack.push([block.clientId, innerBlocks]);
}
});
}
return result;
}
/**
* Helper method to iterate through all blocks, recursing into inner blocks,
* applying a transformation function to each one.
* Returns a flattened object with the transformed blocks.
*
* @param {Array} blocks Blocks to flatten.
* @param {Function} transform Transforming function to be applied to each block.
*
* @return {Array} Flattened object.
*/
function flattenBlocks(blocks, transform = identity) {
const result = [];
const stack = [...blocks];
while (stack.length) {
const {
innerBlocks,
...block
} = stack.shift();
stack.push(...innerBlocks);
result.push([block.clientId, transform(block)]);
}
return result;
}
function getFlattenedClientIds(blocks) {
const result = {};
const stack = [...blocks];
while (stack.length) {
const {
innerBlocks,
...block
} = stack.shift();
stack.push(...innerBlocks);
result[block.clientId] = true;
}
return result;
}
/**
* Given an array of blocks, returns an object containing all blocks, without
* attributes, recursing into inner blocks. Keys correspond to the block client
* ID, the value of which is the attributes object.
*
* @param {Array} blocks Blocks to flatten.
*
* @return {Array} Flattened block attributes object.
*/
function getFlattenedBlocksWithoutAttributes(blocks) {
return flattenBlocks(blocks, block => {
const {
attributes,
...restBlock
} = block;
return restBlock;
});
}
/**
* Given an array of blocks, returns an object containing all block attributes,
* recursing into inner blocks. Keys correspond to the block client ID, the
* value of which is the attributes object.
*
* @param {Array} blocks Blocks to flatten.
*
* @return {Array} Flattened block attributes object.
*/
function getFlattenedBlockAttributes(blocks) {
return flattenBlocks(blocks, block => block.attributes);
}
/**
* Returns true if the two object arguments have the same keys, or false
* otherwise.
*
* @param {Object} a First object.
* @param {Object} b Second object.
*
* @return {boolean} Whether the two objects have the same keys.
*/
function hasSameKeys(a, b) {
return es6_default()(Object.keys(a), Object.keys(b));
}
/**
* Returns true if, given the currently dispatching action and the previously
* dispatched action, the two actions are updating the same block attribute, or
* false otherwise.
*
* @param {Object} action Currently dispatching action.
* @param {Object} lastAction Previously dispatched action.
*
* @return {boolean} Whether actions are updating the same block attribute.
*/
function isUpdatingSameBlockAttribute(action, lastAction) {
return action.type === 'UPDATE_BLOCK_ATTRIBUTES' && lastAction !== undefined && lastAction.type === 'UPDATE_BLOCK_ATTRIBUTES' && es6_default()(action.clientIds, lastAction.clientIds) && hasSameKeys(action.attributes, lastAction.attributes);
}
function updateBlockTreeForBlocks(state, blocks) {
const treeToUpdate = state.tree;
const stack = [...blocks];
const flattenedBlocks = [...blocks];
while (stack.length) {
const block = stack.shift();
stack.push(...block.innerBlocks);
flattenedBlocks.push(...block.innerBlocks);
}
// Create objects before mutating them, that way it's always defined.
for (const block of flattenedBlocks) {
treeToUpdate.set(block.clientId, {});
}
for (const block of flattenedBlocks) {
treeToUpdate.set(block.clientId, Object.assign(treeToUpdate.get(block.clientId), {
...state.byClientId.get(block.clientId),
attributes: state.attributes.get(block.clientId),
innerBlocks: block.innerBlocks.map(subBlock => treeToUpdate.get(subBlock.clientId))
}));
}
}
function updateParentInnerBlocksInTree(state, updatedClientIds, updateChildrenOfUpdatedClientIds = false) {
const treeToUpdate = state.tree;
const uncontrolledParents = new Set([]);
const controlledParents = new Set();
for (const clientId of updatedClientIds) {
let current = updateChildrenOfUpdatedClientIds ? clientId : state.parents.get(clientId);
do {
if (state.controlledInnerBlocks[current]) {
// Should stop on controlled blocks.
// If we reach a controlled parent, break out of the loop.
controlledParents.add(current);
break;
} else {
// Else continue traversing up through parents.
uncontrolledParents.add(current);
current = state.parents.get(current);
}
} while (current !== undefined);
}
// To make sure the order of assignments doesn't matter,
// we first create empty objects and mutates the inner blocks later.
for (const clientId of uncontrolledParents) {
treeToUpdate.set(clientId, {
...treeToUpdate.get(clientId)
});
}
for (const clientId of uncontrolledParents) {
treeToUpdate.get(clientId).innerBlocks = (state.order.get(clientId) || []).map(subClientId => treeToUpdate.get(subClientId));
}
// Controlled parent blocks, need a dedicated key for their inner blocks
// to be used when doing getBlocks( controlledBlockClientId ).
for (const clientId of controlledParents) {
treeToUpdate.set('controlled||' + clientId, {
innerBlocks: (state.order.get(clientId) || []).map(subClientId => treeToUpdate.get(subClientId))
});
}
}
/**
* Higher-order reducer intended to compute full block objects key for each block in the post.
* This is a denormalization to optimize the performance of the getBlock selectors and avoid
* recomputing the block objects and avoid heavy memoization.
*
* @param {Function} reducer Original reducer function.
*
* @return {Function} Enhanced reducer function.
*/
const withBlockTree = reducer => (state = {}, action) => {
const newState = reducer(state, action);
if (newState === state) {
return state;
}
newState.tree = state.tree ? state.tree : new Map();
switch (action.type) {
case 'RECEIVE_BLOCKS':
case 'INSERT_BLOCKS':
{
newState.tree = new Map(newState.tree);
updateBlockTreeForBlocks(newState, action.blocks);
updateParentInnerBlocksInTree(newState, action.rootClientId ? [action.rootClientId] : [''], true);
break;
}
case 'UPDATE_BLOCK':
newState.tree = new Map(newState.tree);
newState.tree.set(action.clientId, {
...newState.tree.get(action.clientId),
...newState.byClientId.get(action.clientId),
attributes: newState.attributes.get(action.clientId)
});
updateParentInnerBlocksInTree(newState, [action.clientId], false);
break;
case 'SYNC_DERIVED_BLOCK_ATTRIBUTES':
case 'UPDATE_BLOCK_ATTRIBUTES':
{
newState.tree = new Map(newState.tree);
action.clientIds.forEach(clientId => {
newState.tree.set(clientId, {
...newState.tree.get(clientId),
attributes: newState.attributes.get(clientId)
});
});
updateParentInnerBlocksInTree(newState, action.clientIds, false);
break;
}
case 'REPLACE_BLOCKS_AUGMENTED_WITH_CHILDREN':
{
const inserterClientIds = getFlattenedClientIds(action.blocks);
newState.tree = new Map(newState.tree);
action.replacedClientIds.forEach(clientId => {
newState.tree.delete(clientId);
// Controlled inner blocks are only removed
// if the block doesn't move to another position
// otherwise their content will be lost.
if (!inserterClientIds[clientId]) {
newState.tree.delete('controlled||' + clientId);
}
});
updateBlockTreeForBlocks(newState, action.blocks);
updateParentInnerBlocksInTree(newState, action.blocks.map(b => b.clientId), false);
// If there are no replaced blocks, it means we're removing blocks so we need to update their parent.
const parentsOfRemovedBlocks = [];
for (const clientId of action.clientIds) {
const parentId = state.parents.get(clientId);
if (parentId !== undefined && (parentId === '' || newState.byClientId.get(parentId))) {
parentsOfRemovedBlocks.push(parentId);
}
}
updateParentInnerBlocksInTree(newState, parentsOfRemovedBlocks, true);
break;
}
case 'REMOVE_BLOCKS_AUGMENTED_WITH_CHILDREN':
const parentsOfRemovedBlocks = [];
for (const clientId of action.clientIds) {
const parentId = state.parents.get(clientId);
if (parentId !== undefined && (parentId === '' || newState.byClientId.get(parentId))) {
parentsOfRemovedBlocks.push(parentId);
}
}
newState.tree = new Map(newState.tree);
action.removedClientIds.forEach(clientId => {
newState.tree.delete(clientId);
newState.tree.delete('controlled||' + clientId);
});
updateParentInnerBlocksInTree(newState, parentsOfRemovedBlocks, true);
break;
case 'MOVE_BLOCKS_TO_POSITION':
{
const updatedBlockUids = [];
if (action.fromRootClientId) {
updatedBlockUids.push(action.fromRootClientId);
} else {
updatedBlockUids.push('');
}
if (action.toRootClientId) {
updatedBlockUids.push(action.toRootClientId);
}
newState.tree = new Map(newState.tree);
updateParentInnerBlocksInTree(newState, updatedBlockUids, true);
break;
}
case 'MOVE_BLOCKS_UP':
case 'MOVE_BLOCKS_DOWN':
{
const updatedBlockUids = [action.rootClientId ? action.rootClientId : ''];
newState.tree = new Map(newState.tree);
updateParentInnerBlocksInTree(newState, updatedBlockUids, true);
break;
}
case 'SAVE_REUSABLE_BLOCK_SUCCESS':
{
const updatedBlockUids = [];
newState.attributes.forEach((attributes, clientId) => {
if (newState.byClientId.get(clientId).name === 'core/block' && attributes.ref === action.updatedId) {
updatedBlockUids.push(clientId);
}
});
newState.tree = new Map(newState.tree);
updatedBlockUids.forEach(clientId => {
newState.tree.set(clientId, {
...newState.byClientId.get(clientId),
attributes: newState.attributes.get(clientId),
innerBlocks: newState.tree.get(clientId).innerBlocks
});
});
updateParentInnerBlocksInTree(newState, updatedBlockUids, false);
}
}
return newState;
};
/**
* Higher-order reducer intended to augment the blocks reducer, assigning an
* `isPersistentChange` property value corresponding to whether a change in
* state can be considered as persistent. All changes are considered persistent
* except when updating the same block attribute as in the previous action.
*
* @param {Function} reducer Original reducer function.
*
* @return {Function} Enhanced reducer function.
*/
function withPersistentBlockChange(reducer) {
let lastAction;
let markNextChangeAsNotPersistent = false;
let explicitPersistent;
return (state, action) => {
let nextState = reducer(state, action);
let nextIsPersistentChange;
if (action.type === 'SET_EXPLICIT_PERSISTENT') {
var _state$isPersistentCh;
explicitPersistent = action.isPersistentChange;
nextIsPersistentChange = (_state$isPersistentCh = state.isPersistentChange) !== null && _state$isPersistentCh !== void 0 ? _state$isPersistentCh : true;
}
if (explicitPersistent !== undefined) {
nextIsPersistentChange = explicitPersistent;
return nextIsPersistentChange === nextState.isPersistentChange ? nextState : {
...nextState,
isPersistentChange: nextIsPersistentChange
};
}
const isExplicitPersistentChange = action.type === 'MARK_LAST_CHANGE_AS_PERSISTENT' || markNextChangeAsNotPersistent;
// Defer to previous state value (or default) unless changing or
// explicitly marking as persistent.
if (state === nextState && !isExplicitPersistentChange) {
var _state$isPersistentCh2;
markNextChangeAsNotPersistent = action.type === 'MARK_NEXT_CHANGE_AS_NOT_PERSISTENT';
nextIsPersistentChange = (_state$isPersistentCh2 = state?.isPersistentChange) !== null && _state$isPersistentCh2 !== void 0 ? _state$isPersistentCh2 : true;
if (state.isPersistentChange === nextIsPersistentChange) {
return state;
}
return {
...nextState,
isPersistentChange: nextIsPersistentChange
};
}
nextState = {
...nextState,
isPersistentChange: isExplicitPersistentChange ? !markNextChangeAsNotPersistent : !isUpdatingSameBlockAttribute(action, lastAction)
};
// In comparing against the previous action, consider only those which
// would have qualified as one which would have been ignored or not
// have resulted in a changed state.
lastAction = action;
markNextChangeAsNotPersistent = action.type === 'MARK_NEXT_CHANGE_AS_NOT_PERSISTENT';
return nextState;
};
}
/**
* Higher-order reducer intended to augment the blocks reducer, assigning an
* `isIgnoredChange` property value corresponding to whether a change in state
* can be considered as ignored. A change is considered ignored when the result
* of an action not incurred by direct user interaction.
*
* @param {Function} reducer Original reducer function.
*
* @return {Function} Enhanced reducer function.
*/
function withIgnoredBlockChange(reducer) {
/**
* Set of action types for which a blocks state change should be ignored.
*
* @type {Set}
*/
const IGNORED_ACTION_TYPES = new Set(['RECEIVE_BLOCKS']);
return (state, action) => {
const nextState = reducer(state, action);
if (nextState !== state) {
nextState.isIgnoredChange = IGNORED_ACTION_TYPES.has(action.type);
}
return nextState;
};
}
/**
* Higher-order reducer targeting the combined blocks reducer, augmenting
* block client IDs in remove action to include cascade of inner blocks.
*
* @param {Function} reducer Original reducer function.
*
* @return {Function} Enhanced reducer function.
*/
const withInnerBlocksRemoveCascade = reducer => (state, action) => {
// Gets all children which need to be removed.
const getAllChildren = clientIds => {
let result = clientIds;
for (let i = 0; i < result.length; i++) {
if (!state.order.get(result[i]) || action.keepControlledInnerBlocks && action.keepControlledInnerBlocks[result[i]]) {
continue;
}
if (result === clientIds) {
result = [...result];
}
result.push(...state.order.get(result[i]));
}
return result;
};
if (state) {
switch (action.type) {
case 'REMOVE_BLOCKS':
action = {
...action,
type: 'REMOVE_BLOCKS_AUGMENTED_WITH_CHILDREN',
removedClientIds: getAllChildren(action.clientIds)
};
break;
case 'REPLACE_BLOCKS':
action = {
...action,
type: 'REPLACE_BLOCKS_AUGMENTED_WITH_CHILDREN',
replacedClientIds: getAllChildren(action.clientIds)
};
break;
}
}
return reducer(state, action);
};
/**
* Higher-order reducer which targets the combined blocks reducer and handles
* the `RESET_BLOCKS` action. When dispatched, this action will replace all
* blocks that exist in the post, leaving blocks that exist only in state (e.g.
* reusable blocks and blocks controlled by inner blocks controllers) alone.
*
* @param {Function} reducer Original reducer function.
*
* @return {Function} Enhanced reducer function.
*/
const withBlockReset = reducer => (state, action) => {
if (action.type === 'RESET_BLOCKS') {
const newState = {
...state,
byClientId: new Map(getFlattenedBlocksWithoutAttributes(action.blocks)),
attributes: new Map(getFlattenedBlockAttributes(action.blocks)),
order: mapBlockOrder(action.blocks),
parents: new Map(mapBlockParents(action.blocks)),
controlledInnerBlocks: {}
};
newState.tree = new Map(state?.tree);
updateBlockTreeForBlocks(newState, action.blocks);
newState.tree.set('', {
innerBlocks: action.blocks.map(subBlock => newState.tree.get(subBlock.clientId))
});
return newState;
}
return reducer(state, action);
};
/**
* Higher-order reducer which targets the combined blocks reducer and handles
* the `REPLACE_INNER_BLOCKS` action. When dispatched, this action the state
* should become equivalent to the execution of a `REMOVE_BLOCKS` action
* containing all the child's of the root block followed by the execution of
* `INSERT_BLOCKS` with the new blocks.
*
* @param {Function} reducer Original reducer function.
*
* @return {Function} Enhanced reducer function.
*/
const withReplaceInnerBlocks = reducer => (state, action) => {
if (action.type !== 'REPLACE_INNER_BLOCKS') {
return reducer(state, action);
}
// Finds every nested inner block controller. We must check the action blocks
// and not just the block parent state because some inner block controllers
// should be deleted if specified, whereas others should not be deleted. If
// a controlled should not be deleted, then we need to avoid deleting its
// inner blocks from the block state because its inner blocks will not be
// attached to the block in the action.
const nestedControllers = {};
if (Object.keys(state.controlledInnerBlocks).length) {
const stack = [...action.blocks];
while (stack.length) {
const {
innerBlocks,
...block
} = stack.shift();
stack.push(...innerBlocks);
if (!!state.controlledInnerBlocks[block.clientId]) {
nestedControllers[block.clientId] = true;
}
}
}
// The `keepControlledInnerBlocks` prop will keep the inner blocks of the
// marked block in the block state so that they can be reattached to the
// marked block when we re-insert everything a few lines below.
let stateAfterBlocksRemoval = state;
if (state.order.get(action.rootClientId)) {
stateAfterBlocksRemoval = reducer(stateAfterBlocksRemoval, {
type: 'REMOVE_BLOCKS',
keepControlledInnerBlocks: nestedControllers,
clientIds: state.order.get(action.rootClientId)
});
}
let stateAfterInsert = stateAfterBlocksRemoval;
if (action.blocks.length) {
stateAfterInsert = reducer(stateAfterInsert, {
...action,
type: 'INSERT_BLOCKS',
index: 0
});
// We need to re-attach the controlled inner blocks to the blocks tree and
// preserve their block order. Otherwise, an inner block controller's blocks
// will be deleted entirely from its entity.
const stateAfterInsertOrder = new Map(stateAfterInsert.order);
Object.keys(nestedControllers).forEach(key => {
if (state.order.get(key)) {
stateAfterInsertOrder.set(key, state.order.get(key));
}
});
stateAfterInsert.order = stateAfterInsertOrder;
stateAfterInsert.tree = new Map(stateAfterInsert.tree);
Object.keys(nestedControllers).forEach(_key => {
const key = `controlled||${_key}`;
if (state.tree.has(key)) {
stateAfterInsert.tree.set(key, state.tree.get(key));
}
});
}
return stateAfterInsert;
};
/**
* Higher-order reducer which targets the combined blocks reducer and handles
* the `SAVE_REUSABLE_BLOCK_SUCCESS` action. This action can't be handled by
* regular reducers and needs a higher-order reducer since it needs access to
* both `byClientId` and `attributes` simultaneously.
*
* @param {Function} reducer Original reducer function.
*
* @return {Function} Enhanced reducer function.
*/
const withSaveReusableBlock = reducer => (state, action) => {
if (state && action.type === 'SAVE_REUSABLE_BLOCK_SUCCESS') {
const {
id,
updatedId
} = action;
// If a temporary reusable block is saved, we swap the temporary id with the final one.
if (id === updatedId) {
return state;
}
state = {
...state
};
state.attributes = new Map(state.attributes);
state.attributes.forEach((attributes, clientId) => {
const {
name
} = state.byClientId.get(clientId);
if (name === 'core/block' && attributes.ref === id) {
state.attributes.set(clientId, {
...attributes,
ref: updatedId
});
}
});
}
return reducer(state, action);
};
/**
* Higher-order reducer which removes blocks from state when switching parent block controlled state.
*
* @param {Function} reducer Original reducer function.
*
* @return {Function} Enhanced reducer function.
*/
const withResetControlledBlocks = reducer => (state, action) => {
if (action.type === 'SET_HAS_CONTROLLED_INNER_BLOCKS') {
// when switching a block from controlled to uncontrolled or inverse,
// we need to remove its content first.
const tempState = reducer(state, {
type: 'REPLACE_INNER_BLOCKS',
rootClientId: action.clientId,
blocks: []
});
return reducer(tempState, action);
}
return reducer(state, action);
};
/**
* Reducer returning the blocks state.
*
* @param {Object} state Current state.
* @param {Object} action Dispatched action.
*
* @return {Object} Updated state.
*/
const blocks = (0,external_wp_compose_namespaceObject.pipe)(external_wp_data_namespaceObject.combineReducers, withSaveReusableBlock,
// Needs to be before withBlockCache.
withBlockTree,
// Needs to be before withInnerBlocksRemoveCascade.
withInnerBlocksRemoveCascade, withReplaceInnerBlocks,
// Needs to be after withInnerBlocksRemoveCascade.
withBlockReset, withPersistentBlockChange, withIgnoredBlockChange, withResetControlledBlocks)({
// The state is using a Map instead of a plain object for performance reasons.
// You can run the "./test/performance.js" unit test to check the impact
// code changes can have on this reducer.
byClientId(state = new Map(), action) {
switch (action.type) {
case 'RECEIVE_BLOCKS':
case 'INSERT_BLOCKS':
{
const newState = new Map(state);
getFlattenedBlocksWithoutAttributes(action.blocks).forEach(([key, value]) => {
newState.set(key, value);
});
return newState;
}
case 'UPDATE_BLOCK':
{
// Ignore updates if block isn't known.
if (!state.has(action.clientId)) {
return state;
}
// Do nothing if only attributes change.
const {
attributes,
...changes
} = action.updates;
if (Object.values(changes).length === 0) {
return state;
}
const newState = new Map(state);
newState.set(action.clientId, {
...state.get(action.clientId),
...changes
});
return newState;
}
case 'REPLACE_BLOCKS_AUGMENTED_WITH_CHILDREN':
{
if (!action.blocks) {
return state;
}
const newState = new Map(state);
action.replacedClientIds.forEach(clientId => {
newState.delete(clientId);
});
getFlattenedBlocksWithoutAttributes(action.blocks).forEach(([key, value]) => {
newState.set(key, value);
});
return newState;
}
case 'REMOVE_BLOCKS_AUGMENTED_WITH_CHILDREN':
{
const newState = new Map(state);
action.removedClientIds.forEach(clientId => {
newState.delete(clientId);
});
return newState;
}
}
return state;
},
// The state is using a Map instead of a plain object for performance reasons.
// You can run the "./test/performance.js" unit test to check the impact
// code changes can have on this reducer.
attributes(state = new Map(), action) {
switch (action.type) {
case 'RECEIVE_BLOCKS':
case 'INSERT_BLOCKS':
{
const newState = new Map(state);
getFlattenedBlockAttributes(action.blocks).forEach(([key, value]) => {
newState.set(key, value);
});
return newState;
}
case 'UPDATE_BLOCK':
{
// Ignore updates if block isn't known or there are no attribute changes.
if (!state.get(action.clientId) || !action.updates.attributes) {
return state;
}
const newState = new Map(state);
newState.set(action.clientId, {
...state.get(action.clientId),
...action.updates.attributes
});
return newState;
}
case 'SYNC_DERIVED_BLOCK_ATTRIBUTES':
case 'UPDATE_BLOCK_ATTRIBUTES':
{
// Avoid a state change if none of the block IDs are known.
if (action.clientIds.every(id => !state.get(id))) {
return state;
}
let hasChange = false;
const newState = new Map(state);
for (const clientId of action.clientIds) {
var _action$attributes;
const updatedAttributeEntries = Object.entries(action.uniqueByBlock ? action.attributes[clientId] : (_action$attributes = action.attributes) !== null && _action$attributes !== void 0 ? _action$attributes : {});
if (updatedAttributeEntries.length === 0) {
continue;
}
let hasUpdatedAttributes = false;
const existingAttributes = state.get(clientId);
const newAttributes = {};
updatedAttributeEntries.forEach(([key, value]) => {
if (existingAttributes[key] !== value) {
hasUpdatedAttributes = true;
newAttributes[key] = value;
}
});
hasChange = hasChange || hasUpdatedAttributes;
if (hasUpdatedAttributes) {
newState.set(clientId, {
...existingAttributes,
...newAttributes
});
}
}
return hasChange ? newState : state;
}
case 'REPLACE_BLOCKS_AUGMENTED_WITH_CHILDREN':
{
if (!action.blocks) {
return state;
}
const newState = new Map(state);
action.replacedClientIds.forEach(clientId => {
newState.delete(clientId);
});
getFlattenedBlockAttributes(action.blocks).forEach(([key, value]) => {
newState.set(key, value);
});
return newState;
}
case 'REMOVE_BLOCKS_AUGMENTED_WITH_CHILDREN':
{
const newState = new Map(state);
action.removedClientIds.forEach(clientId => {
newState.delete(clientId);
});
return newState;
}
}
return state;
},
// The state is using a Map instead of a plain object for performance reasons.
// You can run the "./test/performance.js" unit test to check the impact
// code changes can have on this reducer.
order(state = new Map(), action) {
switch (action.type) {
case 'RECEIVE_BLOCKS':
{
var _state$get;
const blockOrder = mapBlockOrder(action.blocks);
const newState = new Map(state);
blockOrder.forEach((order, clientId) => {
if (clientId !== '') {
newState.set(clientId, order);
}
});
newState.set('', ((_state$get = state.get('')) !== null && _state$get !== void 0 ? _state$get : []).concat(blockOrder['']));
return newState;
}
case 'INSERT_BLOCKS':
{
const {
rootClientId = ''
} = action;
const subState = state.get(rootClientId) || [];
const mappedBlocks = mapBlockOrder(action.blocks, rootClientId);
const {
index = subState.length
} = action;
const newState = new Map(state);
mappedBlocks.forEach((order, clientId) => {
newState.set(clientId, order);
});
newState.set(rootClientId, insertAt(subState, mappedBlocks.get(rootClientId), index));
return newState;
}
case 'MOVE_BLOCKS_TO_POSITION':
{
var _state$get$filter;
const {
fromRootClientId = '',
toRootClientId = '',
clientIds
} = action;
const {
index = state.get(toRootClientId).length
} = action;
// Moving inside the same parent block.
if (fromRootClientId === toRootClientId) {
const subState = state.get(toRootClientId);
const fromIndex = subState.indexOf(clientIds[0]);
const newState = new Map(state);
newState.set(toRootClientId, moveTo(state.get(toRootClientId), fromIndex, index, clientIds.length));
return newState;
}
// Moving from a parent block to another.
const newState = new Map(state);
newState.set(fromRootClientId, (_state$get$filter = state.get(fromRootClientId)?.filter(id => !clientIds.includes(id))) !== null && _state$get$filter !== void 0 ? _state$get$filter : []);
newState.set(toRootClientId, insertAt(state.get(toRootClientId), clientIds, index));
return newState;
}
case 'MOVE_BLOCKS_UP':
{
const {
clientIds,
rootClientId = ''
} = action;
const firstClientId = clientIds[0];
const subState = state.get(rootClientId);
if (!subState.length || firstClientId === subState[0]) {
return state;
}
const firstIndex = subState.indexOf(firstClientId);
const newState = new Map(state);
newState.set(rootClientId, moveTo(subState, firstIndex, firstIndex - 1, clientIds.length));
return newState;
}
case 'MOVE_BLOCKS_DOWN':
{
const {
clientIds,
rootClientId = ''
} = action;
const firstClientId = clientIds[0];
const lastClientId = clientIds[clientIds.length - 1];
const subState = state.get(rootClientId);
if (!subState.length || lastClientId === subState[subState.length - 1]) {
return state;
}
const firstIndex = subState.indexOf(firstClientId);
const newState = new Map(state);
newState.set(rootClientId, moveTo(subState, firstIndex, firstIndex + 1, clientIds.length));
return newState;
}
case 'REPLACE_BLOCKS_AUGMENTED_WITH_CHILDREN':
{
const {
clientIds
} = action;
if (!action.blocks) {
return state;
}
const mappedBlocks = mapBlockOrder(action.blocks);
const newState = new Map(state);
action.replacedClientIds.forEach(clientId => {
newState.delete(clientId);
});
mappedBlocks.forEach((order, clientId) => {
if (clientId !== '') {
newState.set(clientId, order);
}
});
newState.forEach((order, clientId) => {
const newSubOrder = Object.values(order).reduce((result, subClientId) => {
if (subClientId === clientIds[0]) {
return [...result, ...mappedBlocks.get('')];
}
if (clientIds.indexOf(subClientId) === -1) {
result.push(subClientId);
}
return result;
}, []);
newState.set(clientId, newSubOrder);
});
return newState;
}
case 'REMOVE_BLOCKS_AUGMENTED_WITH_CHILDREN':
{
const newState = new Map(state);
// Remove inner block ordering for removed blocks.
action.removedClientIds.forEach(clientId => {
newState.delete(clientId);
});
newState.forEach((order, clientId) => {
var _order$filter;
const newSubOrder = (_order$filter = order?.filter(id => !action.removedClientIds.includes(id))) !== null && _order$filter !== void 0 ? _order$filter : [];
if (newSubOrder.length !== order.length) {
newState.set(clientId, newSubOrder);
}
});
return newState;
}
}
return state;
},
// While technically redundant data as the inverse of `order`, it serves as
// an optimization for the selectors which derive the ancestry of a block.
parents(state = new Map(), action) {
switch (action.type) {
case 'RECEIVE_BLOCKS':
{
const newState = new Map(state);
mapBlockParents(action.blocks).forEach(([key, value]) => {
newState.set(key, value);
});
return newState;
}
case 'INSERT_BLOCKS':
{
const newState = new Map(state);
mapBlockParents(action.blocks, action.rootClientId || '').forEach(([key, value]) => {
newState.set(key, value);
});
return newState;
}
case 'MOVE_BLOCKS_TO_POSITION':
{
const newState = new Map(state);
action.clientIds.forEach(id => {
newState.set(id, action.toRootClientId || '');
});
return newState;
}
case 'REPLACE_BLOCKS_AUGMENTED_WITH_CHILDREN':
{
const newState = new Map(state);
action.replacedClientIds.forEach(clientId => {
newState.delete(clientId);
});
mapBlockParents(action.blocks, state.get(action.clientIds[0])).forEach(([key, value]) => {
newState.set(key, value);
});
return newState;
}
case 'REMOVE_BLOCKS_AUGMENTED_WITH_CHILDREN':
{
const newState = new Map(state);
action.removedClientIds.forEach(clientId => {
newState.delete(clientId);
});
return newState;
}
}
return state;
},
controlledInnerBlocks(state = {}, {
type,
clientId,
hasControlledInnerBlocks
}) {
if (type === 'SET_HAS_CONTROLLED_INNER_BLOCKS') {
return {
...state,
[clientId]: hasControlledInnerBlocks
};
}
return state;
}
});
/**
* Reducer returning visibility status of block interface.
*
* @param {boolean} state Current state.
* @param {Object} action Dispatched action.
*
* @return {boolean} Updated state.
*/
function isBlockInterfaceHidden(state = false, action) {
switch (action.type) {
case 'HIDE_BLOCK_INTERFACE':
return true;
case 'SHOW_BLOCK_INTERFACE':
return false;
}
return state;
}
/**
* Reducer returning typing state.
*
* @param {boolean} state Current state.
* @param {Object} action Dispatched action.
*
* @return {boolean} Updated state.
*/
function isTyping(state = false, action) {
switch (action.type) {
case 'START_TYPING':
return true;
case 'STOP_TYPING':
return false;
}
return state;
}
/**
* Reducer returning dragging state. It is possible for a user to be dragging
* data from outside of the editor, so this state is separate from `draggedBlocks`.
*
* @param {boolean} state Current state.
* @param {Object} action Dispatched action.
*
* @return {boolean} Updated state.
*/
function isDragging(state = false, action) {
switch (action.type) {
case 'START_DRAGGING':
return true;
case 'STOP_DRAGGING':
return false;
}
return state;
}
/**
* Reducer returning dragged block client id.
*
* @param {string[]} state Current state.
* @param {Object} action Dispatched action.
*
* @return {string[]} Updated state.
*/
function draggedBlocks(state = [], action) {
switch (action.type) {
case 'START_DRAGGING_BLOCKS':
return action.clientIds;
case 'STOP_DRAGGING_BLOCKS':
return [];
}
return state;
}
/**
* Reducer tracking the visible blocks.
*
* @param {Record<string,boolean>} state Current state.
* @param {Object} action Dispatched action.
*
* @return {Record<string,boolean>} Block visibility.
*/
function blockVisibility(state = {}, action) {
if (action.type === 'SET_BLOCK_VISIBILITY') {
return {
...state,
...action.updates
};
}
return state;
}
/**
* Internal helper reducer for selectionStart and selectionEnd. Can hold a block
* selection, represented by an object with property clientId.
*
* @param {Object} state Current state.
* @param {Object} action Dispatched action.
*
* @return {Object} Updated state.
*/
function selectionHelper(state = {}, action) {
switch (action.type) {
case 'CLEAR_SELECTED_BLOCK':
{
if (state.clientId) {
return {};
}
return state;
}
case 'SELECT_BLOCK':
if (action.clientId === state.clientId) {
return state;
}
return {
clientId: action.clientId
};
case 'REPLACE_INNER_BLOCKS':
case 'INSERT_BLOCKS':
{
if (!action.updateSelection || !action.blocks.length) {
return state;
}
return {
clientId: action.blocks[0].clientId
};
}
case 'REMOVE_BLOCKS':
if (!action.clientIds || !action.clientIds.length || action.clientIds.indexOf(state.clientId) === -1) {
return state;
}
return {};
case 'REPLACE_BLOCKS':
{
if (action.clientIds.indexOf(state.clientId) === -1) {
return state;
}
const blockToSelect = action.blocks[action.indexToSelect] || action.blocks[action.blocks.length - 1];
if (!blockToSelect) {
return {};
}
if (blockToSelect.clientId === state.clientId) {
return state;
}
return {
clientId: blockToSelect.clientId
};
}
}
return state;
}
/**
* Reducer returning the selection state.
*
* @param {boolean} state Current state.
* @param {Object} action Dispatched action.
*
* @return {boolean} Updated state.
*/
function selection(state = {}, action) {
switch (action.type) {
case 'SELECTION_CHANGE':
if (action.clientId) {
return {
selectionStart: {
clientId: action.clientId,
attributeKey: action.attributeKey,
offset: action.startOffset
},
selectionEnd: {
clientId: action.clientId,
attributeKey: action.attributeKey,
offset: action.endOffset
}
};
}
return {
selectionStart: action.start || state.selectionStart,
selectionEnd: action.end || state.selectionEnd
};
case 'RESET_SELECTION':
const {
selectionStart,
selectionEnd
} = action;
return {
selectionStart,
selectionEnd
};
case 'MULTI_SELECT':
const {
start,
end
} = action;
if (start === state.selectionStart?.clientId && end === state.selectionEnd?.clientId) {
return state;
}
return {
selectionStart: {
clientId: start
},
selectionEnd: {
clientId: end
}
};
case 'RESET_BLOCKS':
const startClientId = state?.selectionStart?.clientId;
const endClientId = state?.selectionEnd?.clientId;
// Do nothing if there's no selected block.
if (!startClientId && !endClientId) {
return state;
}
// If the start of the selection won't exist after reset, remove selection.
if (!action.blocks.some(block => block.clientId === startClientId)) {
return {
selectionStart: {},
selectionEnd: {}
};
}
// If the end of the selection won't exist after reset, collapse selection.
if (!action.blocks.some(block => block.clientId === endClientId)) {
return {
...state,
selectionEnd: state.selectionStart
};
}
}
const selectionStart = selectionHelper(state.selectionStart, action);
const selectionEnd = selectionHelper(state.selectionEnd, action);
if (selectionStart === state.selectionStart && selectionEnd === state.selectionEnd) {
return state;
}
return {
selectionStart,
selectionEnd
};
}
/**
* Reducer returning whether the user is multi-selecting.
*
* @param {boolean} state Current state.
* @param {Object} action Dispatched action.
*
* @return {boolean} Updated state.
*/
function isMultiSelecting(state = false, action) {
switch (action.type) {
case 'START_MULTI_SELECT':
return true;
case 'STOP_MULTI_SELECT':
return false;
}
return state;
}
/**
* Reducer returning whether selection is enabled.
*
* @param {boolean} state Current state.
* @param {Object} action Dispatched action.
*
* @return {boolean} Updated state.
*/
function isSelectionEnabled(state = true, action) {
switch (action.type) {
case 'TOGGLE_SELECTION':
return action.isSelectionEnabled;
}
return state;
}
/**
* Reducer returning the data needed to display a prompt when certain blocks
* are removed, or `false` if no such prompt is requested.
*
* @param {boolean} state Current state.
* @param {Object} action Dispatched action.
*
* @return {Object|false} Data for removal prompt display, if any.
*/
function removalPromptData(state = false, action) {
switch (action.type) {
case 'DISPLAY_BLOCK_REMOVAL_PROMPT':
const {
clientIds,
selectPrevious,
message
} = action;
return {
clientIds,
selectPrevious,
message
};
case 'CLEAR_BLOCK_REMOVAL_PROMPT':
return false;
}
return state;
}
/**
* Reducer returning any rules that a block editor may provide in order to
* prevent a user from accidentally removing certain blocks. These rules are
* then used to display a confirmation prompt to the user. For instance, in the
* Site Editor, the Query Loop block is important enough to warrant such
* confirmation.
*
* The data is a record whose keys are block types (e.g. 'core/query') and
* whose values are the explanation to be shown to users (e.g. 'Query Loop
* displays a list of posts or pages.').
*
* @param {boolean} state Current state.
* @param {Object} action Dispatched action.
*
* @return {Record<string,string>} Updated state.
*/
function blockRemovalRules(state = false, action) {
switch (action.type) {
case 'SET_BLOCK_REMOVAL_RULES':
return action.rules;
}
return state;
}
/**
* Reducer returning the initial block selection.
*
* Currently this in only used to restore the selection after block deletion and
* pasting new content.This reducer should eventually be removed in favour of setting
* selection directly.
*
* @param {boolean} state Current state.
* @param {Object} action Dispatched action.
*
* @return {number|null} Initial position: 0, -1 or null.
*/
function initialPosition(state = null, action) {
if (action.type === 'REPLACE_BLOCKS' && action.initialPosition !== undefined) {
return action.initialPosition;
} else if (['MULTI_SELECT', 'SELECT_BLOCK', 'RESET_SELECTION', 'INSERT_BLOCKS', 'REPLACE_INNER_BLOCKS'].includes(action.type)) {
return action.initialPosition;
}
return state;
}
function blocksMode(state = {}, action) {
if (action.type === 'TOGGLE_BLOCK_MODE') {
const {
clientId
} = action;
return {
...state,
[clientId]: state[clientId] && state[clientId] === 'html' ? 'visual' : 'html'
};
}
return state;
}
/**
* Reducer returning the block insertion point visibility, either null if there
* is not an explicit insertion point assigned, or an object of its `index` and
* `rootClientId`.
*
* @param {Object} state Current state.
* @param {Object} action Dispatched action.
*
* @return {Object} Updated state.
*/
function insertionCue(state = null, action) {
switch (action.type) {
case 'SHOW_INSERTION_POINT':
{
const {
rootClientId,
index,
__unstableWithInserter,
operation,
nearestSide
} = action;
const nextState = {
rootClientId,
index,
__unstableWithInserter,
operation,
nearestSide
};
// Bail out updates if the states are the same.
return es6_default()(state, nextState) ? state : nextState;
}
case 'HIDE_INSERTION_POINT':
return null;
}
return state;
}
/**
* Reducer returning whether the post blocks match the defined template or not.
*
* @param {Object} state Current state.
* @param {Object} action Dispatched action.
*
* @return {boolean} Updated state.
*/
function template(state = {
isValid: true
}, action) {
switch (action.type) {
case 'SET_TEMPLATE_VALIDITY':
return {
...state,
isValid: action.isValid
};
}
return state;
}
/**
* Reducer returning the editor setting.
*
* @param {Object} state Current state.
* @param {Object} action Dispatched action.
*
* @return {Object} Updated state.
*/
function settings(state = SETTINGS_DEFAULTS, action) {
switch (action.type) {
case 'UPDATE_SETTINGS':
{
const updatedSettings = action.reset ? {
...SETTINGS_DEFAULTS,
...action.settings
} : {
...state,
...action.settings
};
Object.defineProperty(updatedSettings, '__unstableIsPreviewMode', {
get() {
external_wp_deprecated_default()('__unstableIsPreviewMode', {
since: '6.8',
alternative: 'isPreviewMode'
});
return this.isPreviewMode;
}
});
return updatedSettings;
}
}
return state;
}
/**
* Reducer returning the user preferences.
*
* @param {Object} state Current state.
* @param {Object} action Dispatched action.
*
* @return {string} Updated state.
*/
function preferences(state = PREFERENCES_DEFAULTS, action) {
switch (action.type) {
case 'INSERT_BLOCKS':
case 'REPLACE_BLOCKS':
{
const nextInsertUsage = action.blocks.reduce((prevUsage, block) => {
const {
attributes,
name: blockName
} = block;
let id = blockName;
// If a block variation match is found change the name to be the same with the
// one that is used for block variations in the Inserter (`getItemFromVariation`).
const match = (0,external_wp_data_namespaceObject.select)(external_wp_blocks_namespaceObject.store).getActiveBlockVariation(blockName, attributes);
if (match?.name) {
id += '/' + match.name;
}
if (blockName === 'core/block') {
id += '/' + attributes.ref;
}
return {
...prevUsage,
[id]: {
time: action.time,
count: prevUsage[id] ? prevUsage[id].count + 1 : 1
}
};
}, state.insertUsage);
return {
...state,
insertUsage: nextInsertUsage
};
}
}
return state;
}
/**
* Reducer returning an object where each key is a block client ID, its value
* representing the settings for its nested blocks.
*
* @param {Object} state Current state.
* @param {Object} action Dispatched action.
*
* @return {Object} Updated state.
*/
const blockListSettings = (state = {}, action) => {
switch (action.type) {
// Even if the replaced blocks have the same client ID, our logic
// should correct the state.
case 'REPLACE_BLOCKS':
case 'REMOVE_BLOCKS':
{
return Object.fromEntries(Object.entries(state).filter(([id]) => !action.clientIds.includes(id)));
}
case 'UPDATE_BLOCK_LIST_SETTINGS':
{
const updates = typeof action.clientId === 'string' ? {
[action.clientId]: action.settings
} : action.clientId;
// Remove settings that are the same as the current state.
for (const clientId in updates) {
if (!updates[clientId]) {
if (!state[clientId]) {
delete updates[clientId];
}
} else if (es6_default()(state[clientId], updates[clientId])) {
delete updates[clientId];
}
}
if (Object.keys(updates).length === 0) {
return state;
}
const merged = {
...state,
...updates
};
for (const clientId in updates) {
if (!updates[clientId]) {
delete merged[clientId];
}
}
return merged;
}
}
return state;
};
/**
* Reducer return an updated state representing the most recent block attribute
* update. The state is structured as an object where the keys represent the
* client IDs of blocks, the values a subset of attributes from the most recent
* block update. The state is always reset to null if the last action is
* anything other than an attributes update.
*
* @param {Object<string,Object>} state Current state.
* @param {Object} action Action object.
*
* @return {[string,Object]} Updated state.
*/
function lastBlockAttributesChange(state = null, action) {
switch (action.type) {
case 'UPDATE_BLOCK':
if (!action.updates.attributes) {
break;
}
return {
[action.clientId]: action.updates.attributes
};
case 'UPDATE_BLOCK_ATTRIBUTES':
return action.clientIds.reduce((accumulator, id) => ({
...accumulator,
[id]: action.uniqueByBlock ? action.attributes[id] : action.attributes
}), {});
}
return state;
}
/**
* Reducer returning current highlighted block.
*
* @param {boolean} state Current highlighted block.
* @param {Object} action Dispatched action.
*
* @return {string} Updated state.
*/
function highlightedBlock(state, action) {
switch (action.type) {
case 'TOGGLE_BLOCK_HIGHLIGHT':
const {
clientId,
isHighlighted
} = action;
if (isHighlighted) {
return clientId;
} else if (state === clientId) {
return null;
}
return state;
case 'SELECT_BLOCK':
if (action.clientId !== state) {
return null;
}
}
return state;
}
/**
* Reducer returning current expanded block in the list view.
*
* @param {string|null} state Current expanded block.
* @param {Object} action Dispatched action.
*
* @return {string|null} Updated state.
*/
function expandedBlock(state = null, action) {
switch (action.type) {
case 'SET_BLOCK_EXPANDED_IN_LIST_VIEW':
return action.clientId;
case 'SELECT_BLOCK':
if (action.clientId !== state) {
return null;
}
}
return state;
}
/**
* Reducer returning the block insertion event list state.
*
* @param {Object} state Current state.
* @param {Object} action Dispatched action.
*
* @return {Object} Updated state.
*/
function lastBlockInserted(state = {}, action) {
switch (action.type) {
case 'INSERT_BLOCKS':
case 'REPLACE_BLOCKS':
if (!action.blocks.length) {
return state;
}
const clientIds = action.blocks.map(block => {
return block.clientId;
});
const source = action.meta?.source;
return {
clientIds,
source
};
case 'RESET_BLOCKS':
return {};
}
return state;
}
/**
* Reducer returning the block that is eding temporarily edited as blocks.
*
* @param {Object} state Current state.
* @param {Object} action Dispatched action.
*
* @return {Object} Updated state.
*/
function temporarilyEditingAsBlocks(state = '', action) {
if (action.type === 'SET_TEMPORARILY_EDITING_AS_BLOCKS') {
return action.temporarilyEditingAsBlocks;
}
return state;
}
/**
* Reducer returning the focus mode that should be used when temporarily edit as blocks finishes.
*
* @param {Object} state Current state.
* @param {Object} action Dispatched action.
*
* @return {Object} Updated state.
*/
function temporarilyEditingFocusModeRevert(state = '', action) {
if (action.type === 'SET_TEMPORARILY_EDITING_AS_BLOCKS') {
return action.focusModeToRevert;
}
return state;
}
/**
* Reducer returning a map of block client IDs to block editing modes.
*
* @param {Map} state Current state.
* @param {Object} action Dispatched action.
*
* @return {Map} Updated state.
*/
function blockEditingModes(state = new Map(), action) {
switch (action.type) {
case 'SET_BLOCK_EDITING_MODE':
if (state.get(action.clientId) === action.mode) {
return state;
}
return new Map(state).set(action.clientId, action.mode);
case 'UNSET_BLOCK_EDITING_MODE':
{
if (!state.has(action.clientId)) {
return state;
}
const newState = new Map(state);
newState.delete(action.clientId);
return newState;
}
case 'RESET_BLOCKS':
{
return state.has('') ? new Map().set('', state.get('')) : state;
}
}
return state;
}
/**
* Reducer returning the clientId of the block settings menu that is currently open.
*
* @param {string|null} state Current state.
* @param {Object} action Dispatched action.
*
* @return {string|null} Updated state.
*/
function openedBlockSettingsMenu(state = null, action) {
if ('SET_OPENED_BLOCK_SETTINGS_MENU' === action.type) {
var _action$clientId;
return (_action$clientId = action?.clientId) !== null && _action$clientId !== void 0 ? _action$clientId : null;
}
return state;
}
/**
* Reducer returning a map of style IDs to style overrides.
*
* @param {Map} state Current state.
* @param {Object} action Dispatched action.
*
* @return {Map} Updated state.
*/
function styleOverrides(state = new Map(), action) {
switch (action.type) {
case 'SET_STYLE_OVERRIDE':
return new Map(state).set(action.id, action.style);
case 'DELETE_STYLE_OVERRIDE':
{
const newState = new Map(state);
newState.delete(action.id);
return newState;
}
}
return state;
}
/**
* Reducer returning a map of the registered inserter media categories.
*
* @param {Array} state Current state.
* @param {Object} action Dispatched action.
*
* @return {Array} Updated state.
*/
function registeredInserterMediaCategories(state = [], action) {
switch (action.type) {
case 'REGISTER_INSERTER_MEDIA_CATEGORY':
return [...state, action.category];
}
return state;
}
/**
* Reducer setting last focused element
*
* @param {boolean} state Current state.
* @param {Object} action Dispatched action.
*
* @return {boolean} Updated state.
*/
function lastFocus(state = false, action) {
switch (action.type) {
case 'LAST_FOCUS':
return action.lastFocus;
}
return state;
}
/**
* Reducer setting currently hovered block.
*
* @param {boolean} state Current state.
* @param {Object} action Dispatched action.
*
* @return {boolean} Updated state.
*/
function hoveredBlockClientId(state = false, action) {
switch (action.type) {
case 'HOVER_BLOCK':
return action.clientId;
}
return state;
}
/**
* Reducer setting zoom out state.
*
* @param {boolean} state Current state.
* @param {Object} action Dispatched action.
*
* @return {number} Updated state.
*/
function zoomLevel(state = 100, action) {
switch (action.type) {
case 'SET_ZOOM_LEVEL':
return action.zoom;
case 'RESET_ZOOM_LEVEL':
return 100;
}
return state;
}
/**
* Reducer setting the insertion point
*
* @param {boolean} state Current state.
* @param {Object} action Dispatched action.
*
* @return {Object} Updated state.
*/
function insertionPoint(state = null, action) {
switch (action.type) {
case 'SET_INSERTION_POINT':
return action.value;
case 'SELECT_BLOCK':
return null;
}
return state;
}
const combinedReducers = (0,external_wp_data_namespaceObject.combineReducers)({
blocks,
isDragging,
isTyping,
isBlockInterfaceHidden,
draggedBlocks,
selection,
isMultiSelecting,
isSelectionEnabled,
initialPosition,
blocksMode,
blockListSettings,
insertionPoint,
insertionCue,
template,
settings,
preferences,
lastBlockAttributesChange,
lastFocus,
expandedBlock,
highlightedBlock,
lastBlockInserted,
temporarilyEditingAsBlocks,
temporarilyEditingFocusModeRevert,
blockVisibility,
blockEditingModes,
styleOverrides,
removalPromptData,
blockRemovalRules,
openedBlockSettingsMenu,
registeredInserterMediaCategories,
hoveredBlockClientId,
zoomLevel
});
/**
* Retrieves a block's tree structure, handling both controlled and uncontrolled inner blocks.
*
* @param {Object} state The current state object.
* @param {string} clientId The client ID of the block to retrieve.
*
* @return {Object|undefined} The block tree object, or undefined if not found. For controlled blocks,
* returns a merged tree with controlled inner blocks.
*/
function getBlockTreeBlock(state, clientId) {
if (clientId === '') {
const rootBlock = state.blocks.tree.get(clientId);
if (!rootBlock) {
return;
}
// Patch the root block to have a clientId property.
// TODO - consider updating the blocks reducer so that the root block has this property.
return {
clientId: '',
...rootBlock
};
}
if (!state.blocks.controlledInnerBlocks[clientId]) {
return state.blocks.tree.get(clientId);
}
const controlledTree = state.blocks.tree.get(`controlled||${clientId}`);
const regularTree = state.blocks.tree.get(clientId);
return {
...regularTree,
innerBlocks: controlledTree?.innerBlocks
};
}
/**
* Recursively traverses through a block tree of a given block and executes a callback for each block.
*
* @param {Object} state The store state.
* @param {string} clientId The clientId of the block to start traversing from.
* @param {Function} callback Function to execute for each block encountered during traversal.
* The callback receives the current block as its argument.
*/
function traverseBlockTree(state, clientId, callback) {
const tree = getBlockTreeBlock(state, clientId);
if (!tree) {
return;
}
callback(tree);
if (!tree?.innerBlocks?.length) {
return;
}
for (const innerBlock of tree?.innerBlocks) {
traverseBlockTree(state, innerBlock.clientId, callback);
}
}
/**
* Checks if a block has a parent in a list of client IDs, and if so returns the client ID of the parent.
*
* @param {Object} state The current state object.
* @param {string} clientId The client ID of the block to search the parents of.
* @param {Array} clientIds The client IDs of the blocks to check.
*
* @return {string|undefined} The client ID of the parent block if found, undefined otherwise.
*/
function findParentInClientIdsList(state, clientId, clientIds) {
if (!clientIds.length) {
return;
}
let parent = state.blocks.parents.get(clientId);
while (parent !== undefined) {
if (clientIds.includes(parent)) {
return parent;
}
parent = state.blocks.parents.get(parent);
}
}
/**
* Checks if a block has any bindings in its metadata attributes.
*
* @param {Object} block The block object to check for bindings.
* @return {boolean} True if the block has bindings, false otherwise.
*/
function hasBindings(block) {
return block?.attributes?.metadata?.bindings && Object.keys(block?.attributes?.metadata?.bindings).length;
}
/**
* Computes and returns derived block editing modes for a given block tree.
*
* This function calculates the editing modes for each block in the tree, taking into account
* various factors such as zoom level, navigation mode, sections, and synced patterns.
*
* @param {Object} state The current state object.
* @param {boolean} isNavMode Whether the navigation mode is active.
* @param {string} treeClientId The client ID of the root block for the tree. Defaults to an empty string.
* @return {Map} A Map containing the derived block editing modes, keyed by block client ID.
*/
function getDerivedBlockEditingModesForTree(state, isNavMode = false, treeClientId = '') {
const isZoomedOut = state?.zoomLevel < 100 || state?.zoomLevel === 'auto-scaled';
const derivedBlockEditingModes = new Map();
// When there are sections, the majority of blocks are disabled,
// so the default block editing mode is set to disabled.
const sectionRootClientId = state.settings?.[sectionRootClientIdKey];
const sectionClientIds = state.blocks.order.get(sectionRootClientId);
const hasDisabledBlocks = Array.from(state.blockEditingModes).some(([, mode]) => mode === 'disabled');
const templatePartClientIds = [];
const syncedPatternClientIds = [];
Object.keys(state.blocks.controlledInnerBlocks).forEach(clientId => {
const block = state.blocks.byClientId?.get(clientId);
if (block?.name === 'core/template-part') {
templatePartClientIds.push(clientId);
}
if (block?.name === 'core/block') {
syncedPatternClientIds.push(clientId);
}
});
traverseBlockTree(state, treeClientId, block => {
const {
clientId,
name: blockName
} = block;
// If the block already has an explicit block editing mode set,
// don't override it.
if (state.blockEditingModes.has(clientId)) {
return;
}
// Disabled explicit block editing modes are inherited by children.
// It's an expensive calculation, so only do it if there are disabled blocks.
if (hasDisabledBlocks) {
// Look through parents to find one with an explicit block editing mode.
let ancestorBlockEditingMode;
let parent = state.blocks.parents.get(clientId);
while (parent !== undefined) {
// There's a chance we only just calculated this for the parent,
// if so we can return that value for a faster lookup.
if (derivedBlockEditingModes.has(parent)) {
ancestorBlockEditingMode = derivedBlockEditingModes.get(parent);
} else if (state.blockEditingModes.has(parent)) {
// Checking the explicit block editing mode will be slower,
// as the block editing mode is more likely to be set on a
// distant ancestor.
ancestorBlockEditingMode = state.blockEditingModes.get(parent);
}
if (ancestorBlockEditingMode) {
break;
}
parent = state.blocks.parents.get(parent);
}
// If the ancestor block editing mode is disabled, it's inherited by the child.
if (ancestorBlockEditingMode === 'disabled') {
derivedBlockEditingModes.set(clientId, 'disabled');
return;
}
}
if (isZoomedOut || isNavMode) {
// If the root block is the section root set its editing mode to contentOnly.
if (clientId === sectionRootClientId) {
derivedBlockEditingModes.set(clientId, 'contentOnly');
return;
}
// There are no sections, so everything else is disabled.
if (!sectionClientIds?.length) {
derivedBlockEditingModes.set(clientId, 'disabled');
return;
}
if (sectionClientIds.includes(clientId)) {
derivedBlockEditingModes.set(clientId, 'contentOnly');
return;
}
// If zoomed out, all blocks that aren't sections or the section root are
// disabled.
if (isZoomedOut) {
derivedBlockEditingModes.set(clientId, 'disabled');
return;
}
const isInSection = !!findParentInClientIdsList(state, clientId, sectionClientIds);
if (!isInSection) {
if (clientId === '') {
derivedBlockEditingModes.set(clientId, 'disabled');
return;
}
// Allow selection of template parts outside of sections.
if (blockName === 'core/template-part') {
derivedBlockEditingModes.set(clientId, 'contentOnly');
return;
}
const isInTemplatePart = !!findParentInClientIdsList(state, clientId, templatePartClientIds);
// Allow contentOnly blocks in template parts outside of sections
// to be editable. Only disable blocks that don't fit this criteria.
if (!isInTemplatePart && !isContentBlock(blockName)) {
derivedBlockEditingModes.set(clientId, 'disabled');
return;
}
}
// Handle synced pattern content so the inner blocks of a synced pattern are
// properly disabled.
if (syncedPatternClientIds.length) {
const parentPatternClientId = findParentInClientIdsList(state, clientId, syncedPatternClientIds);
if (parentPatternClientId) {
// This is a pattern nested in another pattern, it should be disabled.
if (findParentInClientIdsList(state, parentPatternClientId, syncedPatternClientIds)) {
derivedBlockEditingModes.set(clientId, 'disabled');
return;
}
if (hasBindings(block)) {
derivedBlockEditingModes.set(clientId, 'contentOnly');
return;
}
// Synced pattern content without a binding isn't editable
// from the instance, the user has to edit the pattern source,
// so return 'disabled'.
derivedBlockEditingModes.set(clientId, 'disabled');
return;
}
}
if (blockName && isContentBlock(blockName)) {
derivedBlockEditingModes.set(clientId, 'contentOnly');
return;
}
derivedBlockEditingModes.set(clientId, 'disabled');
return;
}
if (syncedPatternClientIds.length) {
// Synced pattern blocks (core/block).
if (syncedPatternClientIds.includes(clientId)) {
// This is a pattern nested in another pattern, it should be disabled.
if (findParentInClientIdsList(state, clientId, syncedPatternClientIds)) {
derivedBlockEditingModes.set(clientId, 'disabled');
return;
}
// Else do nothing, use the default block editing mode.
return;
}
// Inner blocks of synced patterns.
const parentPatternClientId = findParentInClientIdsList(state, clientId, syncedPatternClientIds);
if (parentPatternClientId) {
// This is a pattern nested in another pattern, it should be disabled.
if (findParentInClientIdsList(state, parentPatternClientId, syncedPatternClientIds)) {
derivedBlockEditingModes.set(clientId, 'disabled');
return;
}
if (hasBindings(block)) {
derivedBlockEditingModes.set(clientId, 'contentOnly');
return;
}
// Synced pattern content without a binding isn't editable
// from the instance, the user has to edit the pattern source,
// so return 'disabled'.
derivedBlockEditingModes.set(clientId, 'disabled');
}
}
});
return derivedBlockEditingModes;
}
/**
* Updates the derived block editing modes based on added and removed blocks.
*
* This function handles the updating of block editing modes when blocks are added,
* removed, or moved within the editor.
*
* It only returns a value when modifications are made to the block editing modes.
*
* @param {Object} options The options for updating derived block editing modes.
* @param {Object} options.prevState The previous state object.
* @param {Object} options.nextState The next state object.
* @param {Array} [options.addedBlocks] An array of blocks that were added.
* @param {Array} [options.removedClientIds] An array of client IDs of blocks that were removed.
* @param {boolean} [options.isNavMode] Whether the navigation mode is active.
* @return {Map|undefined} The updated derived block editing modes, or undefined if no changes were made.
*/
function getDerivedBlockEditingModesUpdates({
prevState,
nextState,
addedBlocks,
removedClientIds,
isNavMode = false
}) {
const prevDerivedBlockEditingModes = isNavMode ? prevState.derivedNavModeBlockEditingModes : prevState.derivedBlockEditingModes;
let nextDerivedBlockEditingModes;
// Perform removals before additions to handle cases like the `MOVE_BLOCKS_TO_POSITION` action.
// That action removes a set of clientIds, but adds the same blocks back in a different location.
// If removals were performed after additions, those moved clientIds would be removed incorrectly.
removedClientIds?.forEach(clientId => {
// The actions only receive parent block IDs for removal.
// Recurse through the block tree to ensure all blocks are removed.
// Specifically use the previous state, before the blocks were removed.
traverseBlockTree(prevState, clientId, block => {
if (prevDerivedBlockEditingModes.has(block.clientId)) {
if (!nextDerivedBlockEditingModes) {
nextDerivedBlockEditingModes = new Map(prevDerivedBlockEditingModes);
}
nextDerivedBlockEditingModes.delete(block.clientId);
}
});
});
addedBlocks?.forEach(addedBlock => {
traverseBlockTree(nextState, addedBlock.clientId, block => {
const updates = getDerivedBlockEditingModesForTree(nextState, isNavMode, block.clientId);
if (updates.size) {
if (!nextDerivedBlockEditingModes) {
nextDerivedBlockEditingModes = new Map([...(prevDerivedBlockEditingModes?.size ? prevDerivedBlockEditingModes : []), ...updates]);
} else {
nextDerivedBlockEditingModes = new Map([...(nextDerivedBlockEditingModes?.size ? nextDerivedBlockEditingModes : []), ...updates]);
}
}
});
});
return nextDerivedBlockEditingModes;
}
/**
* Higher-order reducer that adds derived block editing modes to the state.
*
* This function wraps a reducer and enhances it to handle actions that affect
* block editing modes. It updates the derivedBlockEditingModes in the state
* based on various actions such as adding, removing, or moving blocks, or changing
* the editor mode.
*
* @param {Function} reducer The original reducer function to be wrapped.
* @return {Function} A new reducer function that includes derived block editing modes handling.
*/
function withDerivedBlockEditingModes(reducer) {
return (state, action) => {
var _state$derivedBlockEd, _state$derivedNavMode;
const nextState = reducer(state, action);
// An exception is needed here to still recompute the block editing modes when
// the editor mode changes since the editor mode isn't stored within the
// block editor state and changing it won't trigger an altered new state.
if (action.type !== 'SET_EDITOR_MODE' && nextState === state) {
return state;
}
switch (action.type) {
case 'REMOVE_BLOCKS':
{
const nextDerivedBlockEditingModes = getDerivedBlockEditingModesUpdates({
prevState: state,
nextState,
removedClientIds: action.clientIds,
isNavMode: false
});
const nextDerivedNavModeBlockEditingModes = getDerivedBlockEditingModesUpdates({
prevState: state,
nextState,
removedClientIds: action.clientIds,
isNavMode: true
});
if (nextDerivedBlockEditingModes || nextDerivedNavModeBlockEditingModes) {
return {
...nextState,
derivedBlockEditingModes: nextDerivedBlockEditingModes !== null && nextDerivedBlockEditingModes !== void 0 ? nextDerivedBlockEditingModes : state.derivedBlockEditingModes,
derivedNavModeBlockEditingModes: nextDerivedNavModeBlockEditingModes !== null && nextDerivedNavModeBlockEditingModes !== void 0 ? nextDerivedNavModeBlockEditingModes : state.derivedNavModeBlockEditingModes
};
}
break;
}
case 'RECEIVE_BLOCKS':
case 'INSERT_BLOCKS':
{
const nextDerivedBlockEditingModes = getDerivedBlockEditingModesUpdates({
prevState: state,
nextState,
addedBlocks: action.blocks,
isNavMode: false
});
const nextDerivedNavModeBlockEditingModes = getDerivedBlockEditingModesUpdates({
prevState: state,
nextState,
addedBlocks: action.blocks,
isNavMode: true
});
if (nextDerivedBlockEditingModes || nextDerivedNavModeBlockEditingModes) {
return {
...nextState,
derivedBlockEditingModes: nextDerivedBlockEditingModes !== null && nextDerivedBlockEditingModes !== void 0 ? nextDerivedBlockEditingModes : state.derivedBlockEditingModes,
derivedNavModeBlockEditingModes: nextDerivedNavModeBlockEditingModes !== null && nextDerivedNavModeBlockEditingModes !== void 0 ? nextDerivedNavModeBlockEditingModes : state.derivedNavModeBlockEditingModes
};
}
break;
}
case 'SET_BLOCK_EDITING_MODE':
case 'UNSET_BLOCK_EDITING_MODE':
case 'SET_HAS_CONTROLLED_INNER_BLOCKS':
{
const updatedBlock = getBlockTreeBlock(nextState, action.clientId);
// The block might have been removed in which case it'll be
// handled by the `REMOVE_BLOCKS` action.
if (!updatedBlock) {
break;
}
const nextDerivedBlockEditingModes = getDerivedBlockEditingModesUpdates({
prevState: state,
nextState,
removedClientIds: [action.clientId],
addedBlocks: [updatedBlock],
isNavMode: false
});
const nextDerivedNavModeBlockEditingModes = getDerivedBlockEditingModesUpdates({
prevState: state,
nextState,
removedClientIds: [action.clientId],
addedBlocks: [updatedBlock],
isNavMode: true
});
if (nextDerivedBlockEditingModes || nextDerivedNavModeBlockEditingModes) {
return {
...nextState,
derivedBlockEditingModes: nextDerivedBlockEditingModes !== null && nextDerivedBlockEditingModes !== void 0 ? nextDerivedBlockEditingModes : state.derivedBlockEditingModes,
derivedNavModeBlockEditingModes: nextDerivedNavModeBlockEditingModes !== null && nextDerivedNavModeBlockEditingModes !== void 0 ? nextDerivedNavModeBlockEditingModes : state.derivedNavModeBlockEditingModes
};
}
break;
}
case 'REPLACE_BLOCKS':
{
const nextDerivedBlockEditingModes = getDerivedBlockEditingModesUpdates({
prevState: state,
nextState,
addedBlocks: action.blocks,
removedClientIds: action.clientIds,
isNavMode: false
});
const nextDerivedNavModeBlockEditingModes = getDerivedBlockEditingModesUpdates({
prevState: state,
nextState,
addedBlocks: action.blocks,
removedClientIds: action.clientIds,
isNavMode: true
});
if (nextDerivedBlockEditingModes || nextDerivedNavModeBlockEditingModes) {
return {
...nextState,
derivedBlockEditingModes: nextDerivedBlockEditingModes !== null && nextDerivedBlockEditingModes !== void 0 ? nextDerivedBlockEditingModes : state.derivedBlockEditingModes,
derivedNavModeBlockEditingModes: nextDerivedNavModeBlockEditingModes !== null && nextDerivedNavModeBlockEditingModes !== void 0 ? nextDerivedNavModeBlockEditingModes : state.derivedNavModeBlockEditingModes
};
}
break;
}
case 'REPLACE_INNER_BLOCKS':
{
// Get the clientIds of the blocks that are being replaced
// from the old state, before they were removed.
const removedClientIds = state.blocks.order.get(action.rootClientId);
const nextDerivedBlockEditingModes = getDerivedBlockEditingModesUpdates({
prevState: state,
nextState,
addedBlocks: action.blocks,
removedClientIds,
isNavMode: false
});
const nextDerivedNavModeBlockEditingModes = getDerivedBlockEditingModesUpdates({
prevState: state,
nextState,
addedBlocks: action.blocks,
removedClientIds,
isNavMode: true
});
if (nextDerivedBlockEditingModes || nextDerivedNavModeBlockEditingModes) {
return {
...nextState,
derivedBlockEditingModes: nextDerivedBlockEditingModes !== null && nextDerivedBlockEditingModes !== void 0 ? nextDerivedBlockEditingModes : state.derivedBlockEditingModes,
derivedNavModeBlockEditingModes: nextDerivedNavModeBlockEditingModes !== null && nextDerivedNavModeBlockEditingModes !== void 0 ? nextDerivedNavModeBlockEditingModes : state.derivedNavModeBlockEditingModes
};
}
break;
}
case 'MOVE_BLOCKS_TO_POSITION':
{
const addedBlocks = action.clientIds.map(clientId => {
return nextState.blocks.byClientId.get(clientId);
});
const nextDerivedBlockEditingModes = getDerivedBlockEditingModesUpdates({
prevState: state,
nextState,
addedBlocks,
removedClientIds: action.clientIds,
isNavMode: false
});
const nextDerivedNavModeBlockEditingModes = getDerivedBlockEditingModesUpdates({
prevState: state,
nextState,
addedBlocks,
removedClientIds: action.clientIds,
isNavMode: true
});
if (nextDerivedBlockEditingModes || nextDerivedNavModeBlockEditingModes) {
return {
...nextState,
derivedBlockEditingModes: nextDerivedBlockEditingModes !== null && nextDerivedBlockEditingModes !== void 0 ? nextDerivedBlockEditingModes : state.derivedBlockEditingModes,
derivedNavModeBlockEditingModes: nextDerivedNavModeBlockEditingModes !== null && nextDerivedNavModeBlockEditingModes !== void 0 ? nextDerivedNavModeBlockEditingModes : state.derivedNavModeBlockEditingModes
};
}
break;
}
case 'UPDATE_SETTINGS':
{
// Recompute the entire tree if the section root changes.
if (state?.settings?.[sectionRootClientIdKey] !== nextState?.settings?.[sectionRootClientIdKey]) {
return {
...nextState,
derivedBlockEditingModes: getDerivedBlockEditingModesForTree(nextState, false /* Nav mode off */),
derivedNavModeBlockEditingModes: getDerivedBlockEditingModesForTree(nextState, true /* Nav mode on */)
};
}
break;
}
case 'RESET_BLOCKS':
case 'SET_EDITOR_MODE':
case 'RESET_ZOOM_LEVEL':
case 'SET_ZOOM_LEVEL':
{
// Recompute the entire tree if the editor mode or zoom level changes,
// or if all the blocks are reset.
return {
...nextState,
derivedBlockEditingModes: getDerivedBlockEditingModesForTree(nextState, false /* Nav mode off */),
derivedNavModeBlockEditingModes: getDerivedBlockEditingModesForTree(nextState, true /* Nav mode on */)
};
}
}
// If there's no change, the derivedBlockEditingModes from the previous
// state need to be preserved.
nextState.derivedBlockEditingModes = (_state$derivedBlockEd = state?.derivedBlockEditingModes) !== null && _state$derivedBlockEd !== void 0 ? _state$derivedBlockEd : new Map();
nextState.derivedNavModeBlockEditingModes = (_state$derivedNavMode = state?.derivedNavModeBlockEditingModes) !== null && _state$derivedNavMode !== void 0 ? _state$derivedNavMode : new Map();
return nextState;
};
}
function withAutomaticChangeReset(reducer) {
return (state, action) => {
const nextState = reducer(state, action);
if (!state) {
return nextState;
}
// Take over the last value without creating a new reference.
nextState.automaticChangeStatus = state.automaticChangeStatus;
if (action.type === 'MARK_AUTOMATIC_CHANGE') {
return {
...nextState,
automaticChangeStatus: 'pending'
};
}
if (action.type === 'MARK_AUTOMATIC_CHANGE_FINAL' && state.automaticChangeStatus === 'pending') {
return {
...nextState,
automaticChangeStatus: 'final'
};
}
// If there's a change that doesn't affect blocks or selection, maintain
// the current status.
if (nextState.blocks === state.blocks && nextState.selection === state.selection) {
return nextState;
}
// As long as the state is not final, ignore any selection changes.
if (nextState.automaticChangeStatus !== 'final' && nextState.selection !== state.selection) {
return nextState;
}
// Reset the status if blocks change or selection changes (when status is final).
return {
...nextState,
automaticChangeStatus: undefined
};
};
}
/* harmony default export */ const reducer = ((0,external_wp_compose_namespaceObject.pipe)(withDerivedBlockEditingModes, withAutomaticChangeReset)(combinedReducers));
;// external ["wp","primitives"]
const external_wp_primitives_namespaceObject = window["wp"]["primitives"];
;// external "ReactJSXRuntime"
const external_ReactJSXRuntime_namespaceObject = window["ReactJSXRuntime"];
;// ./node_modules/@wordpress/icons/build-module/library/symbol.js
/**
* WordPress dependencies
*/
const symbol = /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_primitives_namespaceObject.SVG, {
xmlns: "http://www.w3.org/2000/svg",
viewBox: "0 0 24 24",
children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_primitives_namespaceObject.Path, {
d: "M21.3 10.8l-5.6-5.6c-.7-.7-1.8-.7-2.5 0l-5.6 5.6c-.7.7-.7 1.8 0 2.5l5.6 5.6c.3.3.8.5 1.2.5s.9-.2 1.2-.5l5.6-5.6c.8-.7.8-1.9.1-2.5zm-1 1.4l-5.6 5.6c-.1.1-.3.1-.4 0l-5.6-5.6c-.1-.1-.1-.3 0-.4l5.6-5.6s.1-.1.2-.1.1 0 .2.1l5.6 5.6c.1.1.1.3 0 .4zm-16.6-.4L10 5.5l-1-1-6.3 6.3c-.7.7-.7 1.8 0 2.5L9 19.5l1.1-1.1-6.3-6.3c-.2 0-.2-.2-.1-.3z"
})
});
/* harmony default export */ const library_symbol = (symbol);
;// external ["wp","richText"]
const external_wp_richText_namespaceObject = window["wp"]["richText"];
;// external ["wp","preferences"]
const external_wp_preferences_namespaceObject = window["wp"]["preferences"];
;// external ["wp","blockSerializationDefaultParser"]
const external_wp_blockSerializationDefaultParser_namespaceObject = window["wp"]["blockSerializationDefaultParser"];
;// ./node_modules/@wordpress/block-editor/build-module/store/constants.js
const STORE_NAME = 'core/block-editor';
;// ./node_modules/@wordpress/block-editor/build-module/components/inserter/block-patterns-tab/utils.js
/**
* WordPress dependencies
*/
const INSERTER_PATTERN_TYPES = {
user: 'user',
theme: 'theme',
directory: 'directory'
};
const INSERTER_SYNC_TYPES = {
full: 'fully',
unsynced: 'unsynced'
};
const allPatternsCategory = {
name: 'allPatterns',
label: (0,external_wp_i18n_namespaceObject._x)('All', 'patterns')
};
const myPatternsCategory = {
name: 'myPatterns',
label: (0,external_wp_i18n_namespaceObject.__)('My patterns')
};
const starterPatternsCategory = {
name: 'core/starter-content',
label: (0,external_wp_i18n_namespaceObject.__)('Starter content')
};
function isPatternFiltered(pattern, sourceFilter, syncFilter) {
const isUserPattern = pattern.name.startsWith('core/block');
const isDirectoryPattern = pattern.source === 'core' || pattern.source?.startsWith('pattern-directory');
// If theme source selected, filter out user created patterns and those from
// the core patterns directory.
if (sourceFilter === INSERTER_PATTERN_TYPES.theme && (isUserPattern || isDirectoryPattern)) {
return true;
}
// If the directory source is selected, filter out user created patterns
// and those bundled with the theme.
if (sourceFilter === INSERTER_PATTERN_TYPES.directory && (isUserPattern || !isDirectoryPattern)) {
return true;
}
// If user source selected, filter out theme patterns.
if (sourceFilter === INSERTER_PATTERN_TYPES.user && pattern.type !== INSERTER_PATTERN_TYPES.user) {
return true;
}
// Filter by sync status.
if (syncFilter === INSERTER_SYNC_TYPES.full && pattern.syncStatus !== '') {
return true;
}
if (syncFilter === INSERTER_SYNC_TYPES.unsynced && pattern.syncStatus !== 'unsynced' && isUserPattern) {
return true;
}
return false;
}
;// ./node_modules/@wordpress/block-editor/build-module/utils/object.js
/**
* Immutably sets a value inside an object. Like `lodash#set`, but returning a
* new object. Treats nullish initial values as empty objects. Clones any
* nested objects. Supports arrays, too.
*
* @param {Object} object Object to set a value in.
* @param {number|string|Array} path Path in the object to modify.
* @param {*} value New value to set.
* @return {Object} Cloned object with the new value set.
*/
function setImmutably(object, path, value) {
// Normalize path
path = Array.isArray(path) ? [...path] : [path];
// Shallowly clone the base of the object
object = Array.isArray(object) ? [...object] : {
...object
};
const leaf = path.pop();
// Traverse object from root to leaf, shallowly cloning at each level
let prev = object;
for (const key of path) {
const lvl = prev[key];
prev = prev[key] = Array.isArray(lvl) ? [...lvl] : {
...lvl
};
}
prev[leaf] = value;
return object;
}
/**
* Helper util to return a value from a certain path of the object.
* Path is specified as either:
* - a string of properties, separated by dots, for example: "x.y".
* - an array of properties, for example `[ 'x', 'y' ]`.
* You can also specify a default value in case the result is nullish.
*
* @param {Object} object Input object.
* @param {string|Array} path Path to the object property.
* @param {*} defaultValue Default value if the value at the specified path is nullish.
* @return {*} Value of the object property at the specified path.
*/
const getValueFromObjectPath = (object, path, defaultValue) => {
var _value;
const arrayPath = Array.isArray(path) ? path : path.split('.');
let value = object;
arrayPath.forEach(fieldName => {
value = value?.[fieldName];
});
return (_value = value) !== null && _value !== void 0 ? _value : defaultValue;
};
/**
* Helper util to filter out objects with duplicate values for a given property.
*
* @param {Object[]} array Array of objects to filter.
* @param {string} property Property to filter unique values by.
*
* @return {Object[]} Array of objects with unique values for the specified property.
*/
function uniqByProperty(array, property) {
const seen = new Set();
return array.filter(item => {
const value = item[property];
return seen.has(value) ? false : seen.add(value);
});
}
;// ./node_modules/@wordpress/block-editor/build-module/store/get-block-settings.js
/**
* WordPress dependencies
*/
/**
* Internal dependencies
*/
const blockedPaths = ['color', 'border', 'dimensions', 'typography', 'spacing'];
const deprecatedFlags = {
'color.palette': settings => settings.colors,
'color.gradients': settings => settings.gradients,
'color.custom': settings => settings.disableCustomColors === undefined ? undefined : !settings.disableCustomColors,
'color.customGradient': settings => settings.disableCustomGradients === undefined ? undefined : !settings.disableCustomGradients,
'typography.fontSizes': settings => settings.fontSizes,
'typography.customFontSize': settings => settings.disableCustomFontSizes === undefined ? undefined : !settings.disableCustomFontSizes,
'typography.lineHeight': settings => settings.enableCustomLineHeight,
'spacing.units': settings => {
if (settings.enableCustomUnits === undefined) {
return;
}
if (settings.enableCustomUnits === true) {
return ['px', 'em', 'rem', 'vh', 'vw', '%'];
}
return settings.enableCustomUnits;
},
'spacing.padding': settings => settings.enableCustomSpacing
};
const prefixedFlags = {
/*
* These were only available in the plugin
* and can be removed when the minimum WordPress version
* for the plugin is 5.9.
*/
'border.customColor': 'border.color',
'border.customStyle': 'border.style',
'border.customWidth': 'border.width',
'typography.customFontStyle': 'typography.fontStyle',
'typography.customFontWeight': 'typography.fontWeight',
'typography.customLetterSpacing': 'typography.letterSpacing',
'typography.customTextDecorations': 'typography.textDecoration',
'typography.customTextTransforms': 'typography.textTransform',
/*
* These were part of WordPress 5.8 and we need to keep them.
*/
'border.customRadius': 'border.radius',
'spacing.customMargin': 'spacing.margin',
'spacing.customPadding': 'spacing.padding',
'typography.customLineHeight': 'typography.lineHeight'
};
/**
* Remove `custom` prefixes for flags that did not land in 5.8.
*
* This provides continued support for `custom` prefixed properties. It will
* be removed once third party devs have had sufficient time to update themes,
* plugins, etc.
*
* @see https://github.com/WordPress/gutenberg/pull/34485
*
* @param {string} path Path to desired value in settings.
* @return {string} The value for defined setting.
*/
const removeCustomPrefixes = path => {
return prefixedFlags[path] || path;
};
function getBlockSettings(state, clientId, ...paths) {
const blockName = getBlockName(state, clientId);
const candidates = [];
if (clientId) {
let id = clientId;
do {
const name = getBlockName(state, id);
if ((0,external_wp_blocks_namespaceObject.hasBlockSupport)(name, '__experimentalSettings', false)) {
candidates.push(id);
}
} while (id = state.blocks.parents.get(id));
}
return paths.map(path => {
if (blockedPaths.includes(path)) {
// eslint-disable-next-line no-console
console.warn('Top level useSetting paths are disabled. Please use a subpath to query the information needed.');
return undefined;
}
// 0. Allow third parties to filter the block's settings at runtime.
let result = (0,external_wp_hooks_namespaceObject.applyFilters)('blockEditor.useSetting.before', undefined, path, clientId, blockName);
if (undefined !== result) {
return result;
}
const normalizedPath = removeCustomPrefixes(path);
// 1. Take settings from the block instance or its ancestors.
// Start from the current block and work our way up the ancestors.
for (const candidateClientId of candidates) {
var _getValueFromObjectPa;
const candidateAtts = getBlockAttributes(state, candidateClientId);
result = (_getValueFromObjectPa = getValueFromObjectPath(candidateAtts.settings?.blocks?.[blockName], normalizedPath)) !== null && _getValueFromObjectPa !== void 0 ? _getValueFromObjectPa : getValueFromObjectPath(candidateAtts.settings, normalizedPath);
if (result !== undefined) {
// Stop the search for more distant ancestors and move on.
break;
}
}
// 2. Fall back to the settings from the block editor store (__experimentalFeatures).
const settings = getSettings(state);
if (result === undefined && blockName) {
result = getValueFromObjectPath(settings.__experimentalFeatures?.blocks?.[blockName], normalizedPath);
}
if (result === undefined) {
result = getValueFromObjectPath(settings.__experimentalFeatures, normalizedPath);
}
// Return if the setting was found in either the block instance or the store.
if (result !== undefined) {
if (external_wp_blocks_namespaceObject.__EXPERIMENTAL_PATHS_WITH_OVERRIDE[normalizedPath]) {
var _ref, _result$custom;
return (_ref = (_result$custom = result.custom) !== null && _result$custom !== void 0 ? _result$custom : result.theme) !== null && _ref !== void 0 ? _ref : result.default;
}
return result;
}
// 3. Otherwise, use deprecated settings.
const deprecatedSettingsValue = deprecatedFlags[normalizedPath]?.(settings);
if (deprecatedSettingsValue !== undefined) {
return deprecatedSettingsValue;
}
// 4. Fallback for typography.dropCap:
// This is only necessary to support typography.dropCap.
// when __experimentalFeatures are not present (core without plugin).
// To remove when __experimentalFeatures are ported to core.
return normalizedPath === 'typography.dropCap' ? true : undefined;
});
}
;// ./node_modules/@wordpress/block-editor/build-module/store/private-selectors.js
/**
* WordPress dependencies
*/
/**
* Internal dependencies
*/
/**
* Returns true if the block interface is hidden, or false otherwise.
*
* @param {Object} state Global application state.
*
* @return {boolean} Whether the block toolbar is hidden.
*/
function private_selectors_isBlockInterfaceHidden(state) {
return state.isBlockInterfaceHidden;
}
/**
* Gets the client ids of the last inserted blocks.
*
* @param {Object} state Global application state.
* @return {Array|undefined} Client Ids of the last inserted block(s).
*/
function getLastInsertedBlocksClientIds(state) {
return state?.lastBlockInserted?.clientIds;
}
function getBlockWithoutAttributes(state, clientId) {
return state.blocks.byClientId.get(clientId);
}
/**
* Returns true if all of the descendants of a block with the given client ID
* have an editing mode of 'disabled', or false otherwise.
*
* @param {Object} state Global application state.
* @param {string} clientId The block client ID.
*
* @return {boolean} Whether the block descendants are disabled.
*/
const isBlockSubtreeDisabled = (state, clientId) => {
const isChildSubtreeDisabled = childClientId => {
return getBlockEditingMode(state, childClientId) === 'disabled' && getBlockOrder(state, childClientId).every(isChildSubtreeDisabled);
};
return getBlockOrder(state, clientId).every(isChildSubtreeDisabled);
};
function getEnabledClientIdsTreeUnmemoized(state, rootClientId) {
const blockOrder = getBlockOrder(state, rootClientId);
const result = [];
for (const clientId of blockOrder) {
const innerBlocks = getEnabledClientIdsTreeUnmemoized(state, clientId);
if (getBlockEditingMode(state, clientId) !== 'disabled') {
result.push({
clientId,
innerBlocks
});
} else {
result.push(...innerBlocks);
}
}
return result;
}
/**
* Returns a tree of block objects with only clientID and innerBlocks set.
* Blocks with a 'disabled' editing mode are not included.
*
* @param {Object} state Global application state.
* @param {?string} rootClientId Optional root client ID of block list.
*
* @return {Object[]} Tree of block objects with only clientID and innerBlocks set.
*/
const getEnabledClientIdsTree = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => (0,external_wp_data_namespaceObject.createSelector)(getEnabledClientIdsTreeUnmemoized, state => [state.blocks.order, state.derivedBlockEditingModes, state.derivedNavModeBlockEditingModes, state.blockEditingModes, state.settings.templateLock, state.blockListSettings, select(STORE_NAME).__unstableGetEditorMode(state)]));
/**
* Returns a list of a given block's ancestors, from top to bottom. Blocks with
* a 'disabled' editing mode are excluded.
*
* @see getBlockParents
*
* @param {Object} state Global application state.
* @param {string} clientId The block client ID.
* @param {boolean} ascending Order results from bottom to top (true) or top
* to bottom (false).
*/
const getEnabledBlockParents = (0,external_wp_data_namespaceObject.createSelector)((state, clientId, ascending = false) => {
return getBlockParents(state, clientId, ascending).filter(parent => getBlockEditingMode(state, parent) !== 'disabled');
}, state => [state.blocks.parents, state.blockEditingModes, state.settings.templateLock, state.blockListSettings]);
/**
* Selector that returns the data needed to display a prompt when certain
* blocks are removed, or `false` if no such prompt is requested.
*
* @param {Object} state Global application state.
*
* @return {Object|false} Data for removal prompt display, if any.
*/
function getRemovalPromptData(state) {
return state.removalPromptData;
}
/**
* Returns true if removal prompt exists, or false otherwise.
*
* @param {Object} state Global application state.
*
* @return {boolean} Whether removal prompt exists.
*/
function getBlockRemovalRules(state) {
return state.blockRemovalRules;
}
/**
* Returns the client ID of the block settings menu that is currently open.
*
* @param {Object} state Global application state.
* @return {string|null} The client ID of the block menu that is currently open.
*/
function getOpenedBlockSettingsMenu(state) {
return state.openedBlockSettingsMenu;
}
/**
* Returns all style overrides, intended to be merged with global editor styles.
*
* Overrides are sorted to match the order of the blocks they relate to. This
* is useful to maintain correct CSS cascade order.
*
* @param {Object} state Global application state.
*
* @return {Array} An array of style ID to style override pairs.
*/
const getStyleOverrides = (0,external_wp_data_namespaceObject.createSelector)(state => {
const clientIds = getClientIdsWithDescendants(state);
const clientIdMap = clientIds.reduce((acc, clientId, index) => {
acc[clientId] = index;
return acc;
}, {});
return [...state.styleOverrides].sort((overrideA, overrideB) => {
var _clientIdMap$clientId, _clientIdMap$clientId2;
// Once the overrides Map is spread to an array, the first element
// is the key, while the second is the override itself including
// the clientId to sort by.
const [, {
clientId: clientIdA
}] = overrideA;
const [, {
clientId: clientIdB
}] = overrideB;
const aIndex = (_clientIdMap$clientId = clientIdMap[clientIdA]) !== null && _clientIdMap$clientId !== void 0 ? _clientIdMap$clientId : -1;
const bIndex = (_clientIdMap$clientId2 = clientIdMap[clientIdB]) !== null && _clientIdMap$clientId2 !== void 0 ? _clientIdMap$clientId2 : -1;
return aIndex - bIndex;
});
}, state => [state.blocks.order, state.styleOverrides]);
/** @typedef {import('./actions').InserterMediaCategory} InserterMediaCategory */
/**
* Returns the registered inserter media categories through the public API.
*
* @param {Object} state Editor state.
*
* @return {InserterMediaCategory[]} Inserter media categories.
*/
function getRegisteredInserterMediaCategories(state) {
return state.registeredInserterMediaCategories;
}
/**
* Returns an array containing the allowed inserter media categories.
* It merges the registered media categories from extenders with the
* core ones. It also takes into account the allowed `mime_types`, which
* can be altered by `upload_mimes` filter and restrict some of them.
*
* @param {Object} state Global application state.
*
* @return {InserterMediaCategory[]} Client IDs of descendants.
*/
const getInserterMediaCategories = (0,external_wp_data_namespaceObject.createSelector)(state => {
const {
settings: {
inserterMediaCategories,
allowedMimeTypes,
enableOpenverseMediaCategory
},
registeredInserterMediaCategories
} = state;
// The allowed `mime_types` can be altered by `upload_mimes` filter and restrict
// some of them. In this case we shouldn't add the category to the available media
// categories list in the inserter.
if (!inserterMediaCategories && !registeredInserterMediaCategories.length || !allowedMimeTypes) {
return;
}
const coreInserterMediaCategoriesNames = inserterMediaCategories?.map(({
name
}) => name) || [];
const mergedCategories = [...(inserterMediaCategories || []), ...(registeredInserterMediaCategories || []).filter(({
name
}) => !coreInserterMediaCategoriesNames.includes(name))];
return mergedCategories.filter(category => {
// Check if Openverse category is enabled.
if (!enableOpenverseMediaCategory && category.name === 'openverse') {
return false;
}
return Object.values(allowedMimeTypes).some(mimeType => mimeType.startsWith(`${category.mediaType}/`));
});
}, state => [state.settings.inserterMediaCategories, state.settings.allowedMimeTypes, state.settings.enableOpenverseMediaCategory, state.registeredInserterMediaCategories]);
/**
* Returns whether there is at least one allowed pattern for inner blocks children.
* This is useful for deferring the parsing of all patterns until needed.
*
* @param {Object} state Editor state.
* @param {string} [rootClientId=null] Target root client ID.
*
* @return {boolean} If there is at least one allowed pattern.
*/
const hasAllowedPatterns = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => (0,external_wp_data_namespaceObject.createSelector)((state, rootClientId = null) => {
const {
getAllPatterns
} = unlock(select(STORE_NAME));
const patterns = getAllPatterns();
const {
allowedBlockTypes
} = getSettings(state);
return patterns.some(pattern => {
const {
inserter = true
} = pattern;
if (!inserter) {
return false;
}
const grammar = getGrammar(pattern);
return checkAllowListRecursive(grammar, allowedBlockTypes) && grammar.every(({
name: blockName
}) => canInsertBlockType(state, blockName, rootClientId));
});
}, (state, rootClientId) => [...getAllPatternsDependants(select)(state), ...getInsertBlockTypeDependants(select)(state, rootClientId)]));
function mapUserPattern(userPattern, __experimentalUserPatternCategories = []) {
return {
name: `core/block/${userPattern.id}`,
id: userPattern.id,
type: INSERTER_PATTERN_TYPES.user,
title: userPattern.title.raw,
categories: userPattern.wp_pattern_category?.map(catId => {
const category = __experimentalUserPatternCategories.find(({
id
}) => id === catId);
return category ? category.slug : catId;
}),
content: userPattern.content.raw,
syncStatus: userPattern.wp_pattern_sync_status
};
}
const getPatternBySlug = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => (0,external_wp_data_namespaceObject.createSelector)((state, patternName) => {
var _state$settings$__exp, _state$settings$selec;
// Only fetch reusable blocks if we know we need them. To do: maybe
// use the entity record API to retrieve the block by slug.
if (patternName?.startsWith('core/block/')) {
const _id = parseInt(patternName.slice('core/block/'.length), 10);
const block = unlock(select(STORE_NAME)).getReusableBlocks().find(({
id
}) => id === _id);
if (!block) {
return null;
}
return mapUserPattern(block, state.settings.__experimentalUserPatternCategories);
}
return [
// This setting is left for back compat.
...((_state$settings$__exp = state.settings.__experimentalBlockPatterns) !== null && _state$settings$__exp !== void 0 ? _state$settings$__exp : []), ...((_state$settings$selec = state.settings[selectBlockPatternsKey]?.(select)) !== null && _state$settings$selec !== void 0 ? _state$settings$selec : [])].find(({
name
}) => name === patternName);
}, (state, patternName) => patternName?.startsWith('core/block/') ? [unlock(select(STORE_NAME)).getReusableBlocks(), state.settings.__experimentalReusableBlocks] : [state.settings.__experimentalBlockPatterns, state.settings[selectBlockPatternsKey]?.(select)]));
const getAllPatterns = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => (0,external_wp_data_namespaceObject.createSelector)(state => {
var _state$settings$__exp2, _state$settings$selec2;
return [...unlock(select(STORE_NAME)).getReusableBlocks().map(userPattern => mapUserPattern(userPattern, state.settings.__experimentalUserPatternCategories)),
// This setting is left for back compat.
...((_state$settings$__exp2 = state.settings.__experimentalBlockPatterns) !== null && _state$settings$__exp2 !== void 0 ? _state$settings$__exp2 : []), ...((_state$settings$selec2 = state.settings[selectBlockPatternsKey]?.(select)) !== null && _state$settings$selec2 !== void 0 ? _state$settings$selec2 : [])].filter((x, index, arr) => index === arr.findIndex(y => x.name === y.name));
}, getAllPatternsDependants(select)));
const EMPTY_ARRAY = [];
const getReusableBlocks = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => state => {
var _ref;
const reusableBlocksSelect = state.settings[reusableBlocksSelectKey];
return (_ref = reusableBlocksSelect ? reusableBlocksSelect(select) : state.settings.__experimentalReusableBlocks) !== null && _ref !== void 0 ? _ref : EMPTY_ARRAY;
});
/**
* Returns the element of the last element that had focus when focus left the editor canvas.
*
* @param {Object} state Block editor state.
*
* @return {Object} Element.
*/
function getLastFocus(state) {
return state.lastFocus;
}
/**
* Returns true if the user is dragging anything, or false otherwise. It is possible for a
* user to be dragging data from outside of the editor, so this selector is separate from
* the `isDraggingBlocks` selector which only returns true if the user is dragging blocks.
*
* @param {Object} state Global application state.
*
* @return {boolean} Whether user is dragging.
*/
function private_selectors_isDragging(state) {
return state.isDragging;
}
/**
* Retrieves the expanded block from the state.
*
* @param {Object} state Block editor state.
*
* @return {string|null} The client ID of the expanded block, if set.
*/
function getExpandedBlock(state) {
return state.expandedBlock;
}
/**
* Retrieves the client ID of the ancestor block that is content locking the block
* with the provided client ID.
*
* @param {Object} state Global application state.
* @param {string} clientId Client Id of the block.
*
* @return {?string} Client ID of the ancestor block that is content locking the block.
*/
const getContentLockingParent = (state, clientId) => {
let current = clientId;
let result;
while (!result && (current = state.blocks.parents.get(current))) {
if (getTemplateLock(state, current) === 'contentOnly') {
result = current;
}
}
return result;
};
/**
* Retrieves the client ID of the parent section block.
*
* @param {Object} state Global application state.
* @param {string} clientId Client Id of the block.
*
* @return {?string} Client ID of the ancestor block that is content locking the block.
*/
const getParentSectionBlock = (state, clientId) => {
let current = clientId;
let result;
while (!result && (current = state.blocks.parents.get(current))) {
if (isSectionBlock(state, current)) {
result = current;
}
}
return result;
};
/**
* Retrieves the client ID is a content locking parent
*
* @param {Object} state Global application state.
* @param {string} clientId Client Id of the block.
*
* @return {boolean} Whether the block is a content locking parent.
*/
function isSectionBlock(state, clientId) {
const blockName = getBlockName(state, clientId);
if (blockName === 'core/block' || getTemplateLock(state, clientId) === 'contentOnly') {
return true;
}
// Template parts become sections in navigation mode.
const _isNavigationMode = isNavigationMode(state);
if (_isNavigationMode && blockName === 'core/template-part') {
return true;
}
const sectionRootClientId = getSectionRootClientId(state);
const sectionClientIds = getBlockOrder(state, sectionRootClientId);
return _isNavigationMode && sectionClientIds.includes(clientId);
}
/**
* Retrieves the client ID of the block that is content locked but is
* currently being temporarily edited as a non-locked block.
*
* @param {Object} state Global application state.
*
* @return {?string} The client ID of the block being temporarily edited as a non-locked block.
*/
function getTemporarilyEditingAsBlocks(state) {
return state.temporarilyEditingAsBlocks;
}
/**
* Returns the focus mode that should be reapplied when the user stops editing
* a content locked blocks as a block without locking.
*
* @param {Object} state Global application state.
*
* @return {?string} The focus mode that should be re-set when temporarily editing as blocks stops.
*/
function getTemporarilyEditingFocusModeToRevert(state) {
return state.temporarilyEditingFocusModeRevert;
}
/**
* Returns the style attributes of multiple blocks.
*
* @param {Object} state Global application state.
* @param {string[]} clientIds An array of block client IDs.
*
* @return {Object} An object where keys are client IDs and values are the corresponding block styles or undefined.
*/
const getBlockStyles = (0,external_wp_data_namespaceObject.createSelector)((state, clientIds) => clientIds.reduce((styles, clientId) => {
styles[clientId] = state.blocks.attributes.get(clientId)?.style;
return styles;
}, {}), (state, clientIds) => [...clientIds.map(clientId => state.blocks.attributes.get(clientId)?.style)]);
/**
* Retrieves the client ID of the block which contains the blocks
* acting as "sections" in the editor. This is typically the "main content"
* of the template/post.
*
* @param {Object} state Editor state.
*
* @return {string|undefined} The section root client ID or undefined if not set.
*/
function getSectionRootClientId(state) {
return state.settings?.[sectionRootClientIdKey];
}
/**
* Returns whether the editor is considered zoomed out.
*
* @param {Object} state Global application state.
* @return {boolean} Whether the editor is zoomed.
*/
function isZoomOut(state) {
return state.zoomLevel === 'auto-scaled' || state.zoomLevel < 100;
}
/**
* Returns whether the zoom level.
*
* @param {Object} state Global application state.
* @return {number|"auto-scaled"} Zoom level.
*/
function getZoomLevel(state) {
return state.zoomLevel;
}
/**
* Finds the closest block where the block is allowed to be inserted.
*
* @param {Object} state Editor state.
* @param {string[] | string} name Block name or names.
* @param {string} clientId Default insertion point.
*
* @return {string} clientID of the closest container when the block name can be inserted.
*/
function getClosestAllowedInsertionPoint(state, name, clientId = '') {
const blockNames = Array.isArray(name) ? name : [name];
const areBlockNamesAllowedInClientId = id => blockNames.every(currentName => canInsertBlockType(state, currentName, id));
// If we're trying to insert at the root level and it's not allowed
// Try the section root instead.
if (!clientId) {
if (areBlockNamesAllowedInClientId(clientId)) {
return clientId;
}
const sectionRootClientId = getSectionRootClientId(state);
if (sectionRootClientId && areBlockNamesAllowedInClientId(sectionRootClientId)) {
return sectionRootClientId;
}
return null;
}
// Traverse the block tree up until we find a place where we can insert.
let current = clientId;
while (current !== null && !areBlockNamesAllowedInClientId(current)) {
const parentClientId = getBlockRootClientId(state, current);
current = parentClientId;
}
return current;
}
function getClosestAllowedInsertionPointForPattern(state, pattern, clientId) {
const {
allowedBlockTypes
} = getSettings(state);
const isAllowed = checkAllowListRecursive(getGrammar(pattern), allowedBlockTypes);
if (!isAllowed) {
return null;
}
const names = getGrammar(pattern).map(({
blockName: name
}) => name);
return getClosestAllowedInsertionPoint(state, names, clientId);
}
/**
* Where the point where the next block will be inserted into.
*
* @param {Object} state
* @return {Object} where the insertion point in the block editor is or null if none is set.
*/
function getInsertionPoint(state) {
return state.insertionPoint;
}
;// ./node_modules/@wordpress/block-editor/build-module/store/utils.js
/**
* WordPress dependencies
*/
/**
* Internal dependencies
*/
const isFiltered = Symbol('isFiltered');
const parsedPatternCache = new WeakMap();
const grammarMapCache = new WeakMap();
function parsePattern(pattern) {
const blocks = (0,external_wp_blocks_namespaceObject.parse)(pattern.content, {
__unstableSkipMigrationLogs: true
});
if (blocks.length === 1) {
blocks[0].attributes = {
...blocks[0].attributes,
metadata: {
...(blocks[0].attributes.metadata || {}),
categories: pattern.categories,
patternName: pattern.name,
name: blocks[0].attributes.metadata?.name || pattern.title
}
};
}
return {
...pattern,
blocks
};
}
function getParsedPattern(pattern) {
let parsedPattern = parsedPatternCache.get(pattern);
if (!parsedPattern) {
parsedPattern = parsePattern(pattern);
parsedPatternCache.set(pattern, parsedPattern);
}
return parsedPattern;
}
function getGrammar(pattern) {
let grammarMap = grammarMapCache.get(pattern);
if (!grammarMap) {
grammarMap = (0,external_wp_blockSerializationDefaultParser_namespaceObject.parse)(pattern.content);
// Block names are null only at the top level for whitespace.
grammarMap = grammarMap.filter(block => block.blockName !== null);
grammarMapCache.set(pattern, grammarMap);
}
return grammarMap;
}
const checkAllowList = (list, item, defaultResult = null) => {
if (typeof list === 'boolean') {
return list;
}
if (Array.isArray(list)) {
// TODO: when there is a canonical way to detect that we are editing a post
// the following check should be changed to something like:
// if ( list.includes( 'core/post-content' ) && getEditorMode() === 'post-content' && item === null )
if (list.includes('core/post-content') && item === null) {
return true;
}
return list.includes(item);
}
return defaultResult;
};
const checkAllowListRecursive = (blocks, allowedBlockTypes) => {
if (typeof allowedBlockTypes === 'boolean') {
return allowedBlockTypes;
}
const blocksQueue = [...blocks];
while (blocksQueue.length > 0) {
const block = blocksQueue.shift();
const isAllowed = checkAllowList(allowedBlockTypes, block.name || block.blockName, true);
if (!isAllowed) {
return false;
}
block.innerBlocks?.forEach(innerBlock => {
blocksQueue.push(innerBlock);
});
}
return true;
};
const getAllPatternsDependants = select => state => {
return [state.settings.__experimentalBlockPatterns, state.settings.__experimentalUserPatternCategories, state.settings.__experimentalReusableBlocks, state.settings[selectBlockPatternsKey]?.(select), state.blockPatterns, unlock(select(STORE_NAME)).getReusableBlocks()];
};
const getInsertBlockTypeDependants = select => (state, rootClientId) => {
return [state.blockListSettings[rootClientId], state.blocks.byClientId.get(rootClientId), state.settings.allowedBlockTypes, state.settings.templateLock, state.blockEditingModes, select(STORE_NAME).__unstableGetEditorMode(state), getSectionRootClientId(state)];
};
;// ./node_modules/@wordpress/block-editor/build-module/utils/sorting.js
/**
* Recursive stable sorting comparator function.
*
* @param {string|Function} field Field to sort by.
* @param {Array} items Items to sort.
* @param {string} order Order, 'asc' or 'desc'.
* @return {Function} Comparison function to be used in a `.sort()`.
*/
const comparator = (field, items, order) => {
return (a, b) => {
let cmpA, cmpB;
if (typeof field === 'function') {
cmpA = field(a);
cmpB = field(b);
} else {
cmpA = a[field];
cmpB = b[field];
}
if (cmpA > cmpB) {
return order === 'asc' ? 1 : -1;
} else if (cmpB > cmpA) {
return order === 'asc' ? -1 : 1;
}
const orderA = items.findIndex(item => item === a);
const orderB = items.findIndex(item => item === b);
// Stable sort: maintaining original array order
if (orderA > orderB) {
return 1;
} else if (orderB > orderA) {
return -1;
}
return 0;
};
};
/**
* Order items by a certain key.
* Supports decorator functions that allow complex picking of a comparison field.
* Sorts in ascending order by default, but supports descending as well.
* Stable sort - maintains original order of equal items.
*
* @param {Array} items Items to order.
* @param {string|Function} field Field to order by.
* @param {string} order Sorting order, `asc` or `desc`.
* @return {Array} Sorted items.
*/
function orderBy(items, field, order = 'asc') {
return items.concat().sort(comparator(field, items, order));
}
;// ./node_modules/@wordpress/block-editor/build-module/store/selectors.js
/**
* WordPress dependencies
*/
/**
* Internal dependencies
*/
/**
* A block selection object.
*
* @typedef {Object} WPBlockSelection
*
* @property {string} clientId A block client ID.
* @property {string} attributeKey A block attribute key.
* @property {number} offset An attribute value offset, based on the rich
* text value. See `wp.richText.create`.
*/
// Module constants.
const MILLISECONDS_PER_HOUR = 3600 * 1000;
const MILLISECONDS_PER_DAY = 24 * 3600 * 1000;
const MILLISECONDS_PER_WEEK = 7 * 24 * 3600 * 1000;
/**
* Shared reference to an empty array for cases where it is important to avoid
* returning a new array reference on every invocation, as in a connected or
* other pure component which performs `shouldComponentUpdate` check on props.
* This should be used as a last resort, since the normalized data should be
* maintained by the reducer result in state.
*
* @type {Array}
*/
const selectors_EMPTY_ARRAY = [];
/**
* Shared reference to an empty Set for cases where it is important to avoid
* returning a new Set reference on every invocation, as in a connected or
* other pure component which performs `shouldComponentUpdate` check on props.
* This should be used as a last resort, since the normalized data should be
* maintained by the reducer result in state.
*
* @type {Set}
*/
const EMPTY_SET = new Set();
const DEFAULT_INSERTER_OPTIONS = {
[isFiltered]: true
};
/**
* Returns a block's name given its client ID, or null if no block exists with
* the client ID.
*
* @param {Object} state Editor state.
* @param {string} clientId Block client ID.
*
* @return {string} Block name.
*/
function getBlockName(state, clientId) {
const block = state.blocks.byClientId.get(clientId);
const socialLinkName = 'core/social-link';
if (external_wp_element_namespaceObject.Platform.OS !== 'web' && block?.name === socialLinkName) {
const attributes = state.blocks.attributes.get(clientId);
const {
service
} = attributes !== null && attributes !== void 0 ? attributes : {};
return service ? `${socialLinkName}-${service}` : socialLinkName;
}
return block ? block.name : null;
}
/**
* Returns whether a block is valid or not.
*
* @param {Object} state Editor state.
* @param {string} clientId Block client ID.
*
* @return {boolean} Is Valid.
*/
function isBlockValid(state, clientId) {
const block = state.blocks.byClientId.get(clientId);
return !!block && block.isValid;
}
/**
* Returns a block's attributes given its client ID, or null if no block exists with
* the client ID.
*
* @param {Object} state Editor state.
* @param {string} clientId Block client ID.
*
* @return {?Object} Block attributes.
*/
function getBlockAttributes(state, clientId) {
const block = state.blocks.byClientId.get(clientId);
if (!block) {
return null;
}
return state.blocks.attributes.get(clientId);
}
/**
* Returns a block given its client ID. This is a parsed copy of the block,
* containing its `blockName`, `clientId`, and current `attributes` state. This
* is not the block's registration settings, which must be retrieved from the
* blocks module registration store.
*
* getBlock recurses through its inner blocks until all its children blocks have
* been retrieved. Note that getBlock will not return the child inner blocks of
* an inner block controller. This is because an inner block controller syncs
* itself with its own entity, and should therefore not be included with the
* blocks of a different entity. For example, say you call `getBlocks( TP )` to
* get the blocks of a template part. If another template part is a child of TP,
* then the nested template part's child blocks will not be returned. This way,
* the template block itself is considered part of the parent, but the children
* are not.
*
* @param {Object} state Editor state.
* @param {string} clientId Block client ID.
*
* @return {Object} Parsed block object.
*/
function getBlock(state, clientId) {
if (!state.blocks.byClientId.has(clientId)) {
return null;
}
return state.blocks.tree.get(clientId);
}
const __unstableGetBlockWithoutInnerBlocks = (0,external_wp_data_namespaceObject.createSelector)((state, clientId) => {
const block = state.blocks.byClientId.get(clientId);
if (!block) {
return null;
}
return {
...block,
attributes: getBlockAttributes(state, clientId)
};
}, (state, clientId) => [state.blocks.byClientId.get(clientId), state.blocks.attributes.get(clientId)]);
/**
* Returns all block objects for the current post being edited as an array in
* the order they appear in the post. Note that this will exclude child blocks
* of nested inner block controllers.
*
* @param {Object} state Editor state.
* @param {?string} rootClientId Optional root client ID of block list.
*
* @return {Object[]} Post blocks.
*/
function getBlocks(state, rootClientId) {
const treeKey = !rootClientId || !areInnerBlocksControlled(state, rootClientId) ? rootClientId || '' : 'controlled||' + rootClientId;
return state.blocks.tree.get(treeKey)?.innerBlocks || selectors_EMPTY_ARRAY;
}
/**
* Returns a stripped down block object containing only its client ID,
* and its inner blocks' client IDs.
*
* @deprecated
*
* @param {Object} state Editor state.
* @param {string} clientId Client ID of the block to get.
*
* @return {Object} Client IDs of the post blocks.
*/
const __unstableGetClientIdWithClientIdsTree = (0,external_wp_data_namespaceObject.createSelector)((state, clientId) => {
external_wp_deprecated_default()("wp.data.select( 'core/block-editor' ).__unstableGetClientIdWithClientIdsTree", {
since: '6.3',
version: '6.5'
});
return {
clientId,
innerBlocks: __unstableGetClientIdsTree(state, clientId)
};
}, state => [state.blocks.order]);
/**
* Returns the block tree represented in the block-editor store from the
* given root, consisting of stripped down block objects containing only
* their client IDs, and their inner blocks' client IDs.
*
* @deprecated
*
* @param {Object} state Editor state.
* @param {?string} rootClientId Optional root client ID of block list.
*
* @return {Object[]} Client IDs of the post blocks.
*/
const __unstableGetClientIdsTree = (0,external_wp_data_namespaceObject.createSelector)((state, rootClientId = '') => {
external_wp_deprecated_default()("wp.data.select( 'core/block-editor' ).__unstableGetClientIdsTree", {
since: '6.3',
version: '6.5'
});
return getBlockOrder(state, rootClientId).map(clientId => __unstableGetClientIdWithClientIdsTree(state, clientId));
}, state => [state.blocks.order]);
/**
* Returns an array containing the clientIds of all descendants of the blocks
* given. Returned ids are ordered first by the order of the ids given, then
* by the order that they appear in the editor.
*
* @param {Object} state Global application state.
* @param {string|string[]} rootIds Client ID(s) for which descendant blocks are to be returned.
*
* @return {Array} Client IDs of descendants.
*/
const getClientIdsOfDescendants = (0,external_wp_data_namespaceObject.createSelector)((state, rootIds) => {
rootIds = Array.isArray(rootIds) ? [...rootIds] : [rootIds];
const ids = [];
// Add the descendants of the root blocks first.
for (const rootId of rootIds) {
const order = state.blocks.order.get(rootId);
if (order) {
ids.push(...order);
}
}
let index = 0;
// Add the descendants of the descendants, recursively.
while (index < ids.length) {
const id = ids[index];
const order = state.blocks.order.get(id);
if (order) {
ids.splice(index + 1, 0, ...order);
}
index++;
}
return ids;
}, state => [state.blocks.order]);
/**
* Returns an array containing the clientIds of the top-level blocks and
* their descendants of any depth (for nested blocks). Ids are returned
* in the same order that they appear in the editor.
*
* @param {Object} state Global application state.
*
* @return {Array} ids of top-level and descendant blocks.
*/
const getClientIdsWithDescendants = state => getClientIdsOfDescendants(state, '');
/**
* Returns the total number of blocks, or the total number of blocks with a specific name in a post.
* The number returned includes nested blocks.
*
* @param {Object} state Global application state.
* @param {?string} blockName Optional block name, if specified only blocks of that type will be counted.
*
* @return {number} Number of blocks in the post, or number of blocks with name equal to blockName.
*/
const getGlobalBlockCount = (0,external_wp_data_namespaceObject.createSelector)((state, blockName) => {
const clientIds = getClientIdsWithDescendants(state);
if (!blockName) {
return clientIds.length;
}
let count = 0;
for (const clientId of clientIds) {
const block = state.blocks.byClientId.get(clientId);
if (block.name === blockName) {
count++;
}
}
return count;
}, state => [state.blocks.order, state.blocks.byClientId]);
/**
* Returns all blocks that match a blockName. Results include nested blocks.
*
* @param {Object} state Global application state.
* @param {string[]} blockName Block name(s) for which clientIds are to be returned.
*
* @return {Array} Array of clientIds of blocks with name equal to blockName.
*/
const getBlocksByName = (0,external_wp_data_namespaceObject.createSelector)((state, blockName) => {
if (!blockName) {
return selectors_EMPTY_ARRAY;
}
const blockNames = Array.isArray(blockName) ? blockName : [blockName];
const clientIds = getClientIdsWithDescendants(state);
const foundBlocks = clientIds.filter(clientId => {
const block = state.blocks.byClientId.get(clientId);
return blockNames.includes(block.name);
});
return foundBlocks.length > 0 ? foundBlocks : selectors_EMPTY_ARRAY;
}, state => [state.blocks.order, state.blocks.byClientId]);
/**
* Returns all global blocks that match a blockName. Results include nested blocks.
*
* @deprecated
*
* @param {Object} state Global application state.
* @param {string[]} blockName Block name(s) for which clientIds are to be returned.
*
* @return {Array} Array of clientIds of blocks with name equal to blockName.
*/
function __experimentalGetGlobalBlocksByName(state, blockName) {
external_wp_deprecated_default()("wp.data.select( 'core/block-editor' ).__experimentalGetGlobalBlocksByName", {
since: '6.5',
alternative: `wp.data.select( 'core/block-editor' ).getBlocksByName`
});
return getBlocksByName(state, blockName);
}
/**
* Given an array of block client IDs, returns the corresponding array of block
* objects.
*
* @param {Object} state Editor state.
* @param {string[]} clientIds Client IDs for which blocks are to be returned.
*
* @return {WPBlock[]} Block objects.
*/
const getBlocksByClientId = (0,external_wp_data_namespaceObject.createSelector)((state, clientIds) => (Array.isArray(clientIds) ? clientIds : [clientIds]).map(clientId => getBlock(state, clientId)), (state, clientIds) => (Array.isArray(clientIds) ? clientIds : [clientIds]).map(clientId => state.blocks.tree.get(clientId)));
/**
* Given an array of block client IDs, returns the corresponding array of block
* names.
*
* @param {Object} state Editor state.
* @param {string[]} clientIds Client IDs for which block names are to be returned.
*
* @return {string[]} Block names.
*/
const getBlockNamesByClientId = (0,external_wp_data_namespaceObject.createSelector)((state, clientIds) => getBlocksByClientId(state, clientIds).filter(Boolean).map(block => block.name), (state, clientIds) => getBlocksByClientId(state, clientIds));
/**
* Returns the number of blocks currently present in the post.
*
* @param {Object} state Editor state.
* @param {?string} rootClientId Optional root client ID of block list.
*
* @return {number} Number of blocks in the post.
*/
function getBlockCount(state, rootClientId) {
return getBlockOrder(state, rootClientId).length;
}
/**
* Returns the current selection start block client ID, attribute key and text
* offset.
*
* @param {Object} state Block editor state.
*
* @return {WPBlockSelection} Selection start information.
*/
function getSelectionStart(state) {
return state.selection.selectionStart;
}
/**
* Returns the current selection end block client ID, attribute key and text
* offset.
*
* @param {Object} state Block editor state.
*
* @return {WPBlockSelection} Selection end information.
*/
function getSelectionEnd(state) {
return state.selection.selectionEnd;
}
/**
* Returns the current block selection start. This value may be null, and it
* may represent either a singular block selection or multi-selection start.
* A selection is singular if its start and end match.
*
* @param {Object} state Global application state.
*
* @return {?string} Client ID of block selection start.
*/
function getBlockSelectionStart(state) {
return state.selection.selectionStart.clientId;
}
/**
* Returns the current block selection end. This value may be null, and it
* may represent either a singular block selection or multi-selection end.
* A selection is singular if its start and end match.
*
* @param {Object} state Global application state.
*
* @return {?string} Client ID of block selection end.
*/
function getBlockSelectionEnd(state) {
return state.selection.selectionEnd.clientId;
}
/**
* Returns the number of blocks currently selected in the post.
*
* @param {Object} state Global application state.
*
* @return {number} Number of blocks selected in the post.
*/
function getSelectedBlockCount(state) {
const multiSelectedBlockCount = getMultiSelectedBlockClientIds(state).length;
if (multiSelectedBlockCount) {
return multiSelectedBlockCount;
}
return state.selection.selectionStart.clientId ? 1 : 0;
}
/**
* Returns true if there is a single selected block, or false otherwise.
*
* @param {Object} state Editor state.
*
* @return {boolean} Whether a single block is selected.
*/
function hasSelectedBlock(state) {
const {
selectionStart,
selectionEnd
} = state.selection;
return !!selectionStart.clientId && selectionStart.clientId === selectionEnd.clientId;
}
/**
* Returns the currently selected block client ID, or null if there is no
* selected block.
*
* @param {Object} state Editor state.
*
* @return {?string} Selected block client ID.
*/
function getSelectedBlockClientId(state) {
const {
selectionStart,
selectionEnd
} = state.selection;
const {
clientId
} = selectionStart;
if (!clientId || clientId !== selectionEnd.clientId) {
return null;
}
return clientId;
}
/**
* Returns the currently selected block, or null if there is no selected block.
*
* @param {Object} state Global application state.
*
* @example
*
*```js
* import { select } from '@wordpress/data'
* import { store as blockEditorStore } from '@wordpress/block-editor'
*
* // Set initial active block client ID
* let activeBlockClientId = null
*
* const getActiveBlockData = () => {
* const activeBlock = select(blockEditorStore).getSelectedBlock()
*
* if (activeBlock && activeBlock.clientId !== activeBlockClientId) {
* activeBlockClientId = activeBlock.clientId
*
* // Get active block name and attributes
* const activeBlockName = activeBlock.name
* const activeBlockAttributes = activeBlock.attributes
*
* // Log active block name and attributes
* console.log(activeBlockName, activeBlockAttributes)
* }
* }
*
* // Subscribe to changes in the editor
* // wp.data.subscribe(() => {
* // getActiveBlockData()
* // })
*
* // Update active block data on click
* // onclick="getActiveBlockData()"
*```
*
* @return {?Object} Selected block.
*/
function getSelectedBlock(state) {
const clientId = getSelectedBlockClientId(state);
return clientId ? getBlock(state, clientId) : null;
}
/**
* Given a block client ID, returns the root block from which the block is
* nested, an empty string for top-level blocks, or null if the block does not
* exist.
*
* @param {Object} state Editor state.
* @param {string} clientId Block from which to find root client ID.
*
* @return {?string} Root client ID, if exists
*/
function getBlockRootClientId(state, clientId) {
var _state$blocks$parents;
return (_state$blocks$parents = state.blocks.parents.get(clientId)) !== null && _state$blocks$parents !== void 0 ? _state$blocks$parents : null;
}
/**
* Given a block client ID, returns the list of all its parents from top to bottom.
*
* @param {Object} state Editor state.
* @param {string} clientId Block from which to find root client ID.
* @param {boolean} ascending Order results from bottom to top (true) or top to bottom (false).
*
* @return {Array} ClientIDs of the parent blocks.
*/
const getBlockParents = (0,external_wp_data_namespaceObject.createSelector)((state, clientId, ascending = false) => {
const parents = [];
let current = clientId;
while (current = state.blocks.parents.get(current)) {
parents.push(current);
}
if (!parents.length) {
return selectors_EMPTY_ARRAY;
}
return ascending ? parents : parents.reverse();
}, state => [state.blocks.parents]);
/**
* Given a block client ID and a block name, returns the list of all its parents
* from top to bottom, filtered by the given name(s). For example, if passed
* 'core/group' as the blockName, it will only return parents which are group
* blocks. If passed `[ 'core/group', 'core/cover']`, as the blockName, it will
* return parents which are group blocks and parents which are cover blocks.
*
* @param {Object} state Editor state.
* @param {string} clientId Block from which to find root client ID.
* @param {string|string[]} blockName Block name(s) to filter.
* @param {boolean} ascending Order results from bottom to top (true) or top to bottom (false).
*
* @return {Array} ClientIDs of the parent blocks.
*/
const getBlockParentsByBlockName = (0,external_wp_data_namespaceObject.createSelector)((state, clientId, blockName, ascending = false) => {
const parents = getBlockParents(state, clientId, ascending);
const hasName = Array.isArray(blockName) ? name => blockName.includes(name) : name => blockName === name;
return parents.filter(id => hasName(getBlockName(state, id)));
}, state => [state.blocks.parents]);
/**
* Given a block client ID, returns the root of the hierarchy from which the block is nested, return the block itself for root level blocks.
*
* @param {Object} state Editor state.
* @param {string} clientId Block from which to find root client ID.
*
* @return {string} Root client ID
*/
function getBlockHierarchyRootClientId(state, clientId) {
let current = clientId;
let parent;
do {
parent = current;
current = state.blocks.parents.get(current);
} while (current);
return parent;
}
/**
* Given a block client ID, returns the lowest common ancestor with selected client ID.
*
* @param {Object} state Editor state.
* @param {string} clientId Block from which to find common ancestor client ID.
*
* @return {string} Common ancestor client ID or undefined
*/
function getLowestCommonAncestorWithSelectedBlock(state, clientId) {
const selectedId = getSelectedBlockClientId(state);
const clientParents = [...getBlockParents(state, clientId), clientId];
const selectedParents = [...getBlockParents(state, selectedId), selectedId];
let lowestCommonAncestor;
const maxDepth = Math.min(clientParents.length, selectedParents.length);
for (let index = 0; index < maxDepth; index++) {
if (clientParents[index] === selectedParents[index]) {
lowestCommonAncestor = clientParents[index];
} else {
break;
}
}
return lowestCommonAncestor;
}
/**
* Returns the client ID of the block adjacent one at the given reference
* startClientId and modifier directionality. Defaults start startClientId to
* the selected block, and direction as next block. Returns null if there is no
* adjacent block.
*
* @param {Object} state Editor state.
* @param {?string} startClientId Optional client ID of block from which to
* search.
* @param {?number} modifier Directionality multiplier (1 next, -1
* previous).
*
* @return {?string} Return the client ID of the block, or null if none exists.
*/
function getAdjacentBlockClientId(state, startClientId, modifier = 1) {
// Default to selected block.
if (startClientId === undefined) {
startClientId = getSelectedBlockClientId(state);
}
// Try multi-selection starting at extent based on modifier.
if (startClientId === undefined) {
if (modifier < 0) {
startClientId = getFirstMultiSelectedBlockClientId(state);
} else {
startClientId = getLastMultiSelectedBlockClientId(state);
}
}
// Validate working start client ID.
if (!startClientId) {
return null;
}
// Retrieve start block root client ID, being careful to allow the falsey
// empty string top-level root by explicitly testing against null.
const rootClientId = getBlockRootClientId(state, startClientId);
if (rootClientId === null) {
return null;
}
const {
order
} = state.blocks;
const orderSet = order.get(rootClientId);
const index = orderSet.indexOf(startClientId);
const nextIndex = index + 1 * modifier;
// Block was first in set and we're attempting to get previous.
if (nextIndex < 0) {
return null;
}
// Block was last in set and we're attempting to get next.
if (nextIndex === orderSet.length) {
return null;
}
// Assume incremented index is within the set.
return orderSet[nextIndex];
}
/**
* Returns the previous block's client ID from the given reference start ID.
* Defaults start to the selected block. Returns null if there is no previous
* block.
*
* @param {Object} state Editor state.
* @param {?string} startClientId Optional client ID of block from which to
* search.
*
* @return {?string} Adjacent block's client ID, or null if none exists.
*/
function getPreviousBlockClientId(state, startClientId) {
return getAdjacentBlockClientId(state, startClientId, -1);
}
/**
* Returns the next block's client ID from the given reference start ID.
* Defaults start to the selected block. Returns null if there is no next
* block.
*
* @param {Object} state Editor state.
* @param {?string} startClientId Optional client ID of block from which to
* search.
*
* @return {?string} Adjacent block's client ID, or null if none exists.
*/
function getNextBlockClientId(state, startClientId) {
return getAdjacentBlockClientId(state, startClientId, 1);
}
/* eslint-disable jsdoc/valid-types */
/**
* Returns the initial caret position for the selected block.
* This position is to used to position the caret properly when the selected block changes.
* If the current block is not a RichText, having initial position set to 0 means "focus block"
*
* @param {Object} state Global application state.
*
* @return {0|-1|null} Initial position.
*/
function getSelectedBlocksInitialCaretPosition(state) {
/* eslint-enable jsdoc/valid-types */
return state.initialPosition;
}
/**
* Returns the current selection set of block client IDs (multiselection or single selection).
*
* @param {Object} state Editor state.
*
* @return {Array} Multi-selected block client IDs.
*/
const getSelectedBlockClientIds = (0,external_wp_data_namespaceObject.createSelector)(state => {
const {
selectionStart,
selectionEnd
} = state.selection;
if (!selectionStart.clientId || !selectionEnd.clientId) {
return selectors_EMPTY_ARRAY;
}
if (selectionStart.clientId === selectionEnd.clientId) {
return [selectionStart.clientId];
}
// Retrieve root client ID to aid in retrieving relevant nested block
// order, being careful to allow the falsey empty string top-level root
// by explicitly testing against null.
const rootClientId = getBlockRootClientId(state, selectionStart.clientId);
if (rootClientId === null) {
return selectors_EMPTY_ARRAY;
}
const blockOrder = getBlockOrder(state, rootClientId);
const startIndex = blockOrder.indexOf(selectionStart.clientId);
const endIndex = blockOrder.indexOf(selectionEnd.clientId);
if (startIndex > endIndex) {
return blockOrder.slice(endIndex, startIndex + 1);
}
return blockOrder.slice(startIndex, endIndex + 1);
}, state => [state.blocks.order, state.selection.selectionStart.clientId, state.selection.selectionEnd.clientId]);
/**
* Returns the current multi-selection set of block client IDs, or an empty
* array if there is no multi-selection.
*
* @param {Object} state Editor state.
*
* @return {Array} Multi-selected block client IDs.
*/
function getMultiSelectedBlockClientIds(state) {
const {
selectionStart,
selectionEnd
} = state.selection;
if (selectionStart.clientId === selectionEnd.clientId) {
return selectors_EMPTY_ARRAY;
}
return getSelectedBlockClientIds(state);
}
/**
* Returns the current multi-selection set of blocks, or an empty array if
* there is no multi-selection.
*
* @param {Object} state Editor state.
*
* @return {Array} Multi-selected block objects.
*/
const getMultiSelectedBlocks = (0,external_wp_data_namespaceObject.createSelector)(state => {
const multiSelectedBlockClientIds = getMultiSelectedBlockClientIds(state);
if (!multiSelectedBlockClientIds.length) {
return selectors_EMPTY_ARRAY;
}
return multiSelectedBlockClientIds.map(clientId => getBlock(state, clientId));
}, state => [...getSelectedBlockClientIds.getDependants(state), state.blocks.byClientId, state.blocks.order, state.blocks.attributes]);
/**
* Returns the client ID of the first block in the multi-selection set, or null
* if there is no multi-selection.
*
* @param {Object} state Editor state.
*
* @return {?string} First block client ID in the multi-selection set.
*/
function getFirstMultiSelectedBlockClientId(state) {
return getMultiSelectedBlockClientIds(state)[0] || null;
}
/**
* Returns the client ID of the last block in the multi-selection set, or null
* if there is no multi-selection.
*
* @param {Object} state Editor state.
*
* @return {?string} Last block client ID in the multi-selection set.
*/
function getLastMultiSelectedBlockClientId(state) {
const selectedClientIds = getMultiSelectedBlockClientIds(state);
return selectedClientIds[selectedClientIds.length - 1] || null;
}
/**
* Returns true if a multi-selection exists, and the block corresponding to the
* specified client ID is the first block of the multi-selection set, or false
* otherwise.
*
* @param {Object} state Editor state.
* @param {string} clientId Block client ID.
*
* @return {boolean} Whether block is first in multi-selection.
*/
function isFirstMultiSelectedBlock(state, clientId) {
return getFirstMultiSelectedBlockClientId(state) === clientId;
}
/**
* Returns true if the client ID occurs within the block multi-selection, or
* false otherwise.
*
* @param {Object} state Editor state.
* @param {string} clientId Block client ID.
*
* @return {boolean} Whether block is in multi-selection set.
*/
function isBlockMultiSelected(state, clientId) {
return getMultiSelectedBlockClientIds(state).indexOf(clientId) !== -1;
}
/**
* Returns true if an ancestor of the block is multi-selected, or false
* otherwise.
*
* @param {Object} state Editor state.
* @param {string} clientId Block client ID.
*
* @return {boolean} Whether an ancestor of the block is in multi-selection
* set.
*/
const isAncestorMultiSelected = (0,external_wp_data_namespaceObject.createSelector)((state, clientId) => {
let ancestorClientId = clientId;
let isMultiSelected = false;
while (ancestorClientId && !isMultiSelected) {
ancestorClientId = getBlockRootClientId(state, ancestorClientId);
isMultiSelected = isBlockMultiSelected(state, ancestorClientId);
}
return isMultiSelected;
}, state => [state.blocks.order, state.selection.selectionStart.clientId, state.selection.selectionEnd.clientId]);
/**
* Returns the client ID of the block which begins the multi-selection set, or
* null if there is no multi-selection.
*
* This is not necessarily the first client ID in the selection.
*
* @see getFirstMultiSelectedBlockClientId
*
* @param {Object} state Editor state.
*
* @return {?string} Client ID of block beginning multi-selection.
*/
function getMultiSelectedBlocksStartClientId(state) {
const {
selectionStart,
selectionEnd
} = state.selection;
if (selectionStart.clientId === selectionEnd.clientId) {
return null;
}
return selectionStart.clientId || null;
}
/**
* Returns the client ID of the block which ends the multi-selection set, or
* null if there is no multi-selection.
*
* This is not necessarily the last client ID in the selection.
*
* @see getLastMultiSelectedBlockClientId
*
* @param {Object} state Editor state.
*
* @return {?string} Client ID of block ending multi-selection.
*/
function getMultiSelectedBlocksEndClientId(state) {
const {
selectionStart,
selectionEnd
} = state.selection;
if (selectionStart.clientId === selectionEnd.clientId) {
return null;
}
return selectionEnd.clientId || null;
}
/**
* Returns true if the selection is not partial.
*
* @param {Object} state Editor state.
*
* @return {boolean} Whether the selection is mergeable.
*/
function __unstableIsFullySelected(state) {
const selectionAnchor = getSelectionStart(state);
const selectionFocus = getSelectionEnd(state);
return !selectionAnchor.attributeKey && !selectionFocus.attributeKey && typeof selectionAnchor.offset === 'undefined' && typeof selectionFocus.offset === 'undefined';
}
/**
* Returns true if the selection is collapsed.
*
* @param {Object} state Editor state.
*
* @return {boolean} Whether the selection is collapsed.
*/
function __unstableIsSelectionCollapsed(state) {
const selectionAnchor = getSelectionStart(state);
const selectionFocus = getSelectionEnd(state);
return !!selectionAnchor && !!selectionFocus && selectionAnchor.clientId === selectionFocus.clientId && selectionAnchor.attributeKey === selectionFocus.attributeKey && selectionAnchor.offset === selectionFocus.offset;
}
function __unstableSelectionHasUnmergeableBlock(state) {
return getSelectedBlockClientIds(state).some(clientId => {
const blockName = getBlockName(state, clientId);
const blockType = (0,external_wp_blocks_namespaceObject.getBlockType)(blockName);
return !blockType.merge;
});
}
/**
* Check whether the selection is mergeable.
*
* @param {Object} state Editor state.
* @param {boolean} isForward Whether to merge forwards.
*
* @return {boolean} Whether the selection is mergeable.
*/
function __unstableIsSelectionMergeable(state, isForward) {
const selectionAnchor = getSelectionStart(state);
const selectionFocus = getSelectionEnd(state);
// It's not mergeable if the start and end are within the same block.
if (selectionAnchor.clientId === selectionFocus.clientId) {
return false;
}
// It's not mergeable if there's no rich text selection.
if (!selectionAnchor.attributeKey || !selectionFocus.attributeKey || typeof selectionAnchor.offset === 'undefined' || typeof selectionFocus.offset === 'undefined') {
return false;
}
const anchorRootClientId = getBlockRootClientId(state, selectionAnchor.clientId);
const focusRootClientId = getBlockRootClientId(state, selectionFocus.clientId);
// It's not mergeable if the selection doesn't start and end in the same
// block list. Maybe in the future it should be allowed.
if (anchorRootClientId !== focusRootClientId) {
return false;
}
const blockOrder = getBlockOrder(state, anchorRootClientId);
const anchorIndex = blockOrder.indexOf(selectionAnchor.clientId);
const focusIndex = blockOrder.indexOf(selectionFocus.clientId);
// Reassign selection start and end based on order.
let selectionStart, selectionEnd;
if (anchorIndex > focusIndex) {
selectionStart = selectionFocus;
selectionEnd = selectionAnchor;
} else {
selectionStart = selectionAnchor;
selectionEnd = selectionFocus;
}
const targetBlockClientId = isForward ? selectionEnd.clientId : selectionStart.clientId;
const blockToMergeClientId = isForward ? selectionStart.clientId : selectionEnd.clientId;
const targetBlockName = getBlockName(state, targetBlockClientId);
const targetBlockType = (0,external_wp_blocks_namespaceObject.getBlockType)(targetBlockName);
if (!targetBlockType.merge) {
return false;
}
const blockToMerge = getBlock(state, blockToMergeClientId);
// It's mergeable if the blocks are of the same type.
if (blockToMerge.name === targetBlockName) {
return true;
}
// If the blocks are of a different type, try to transform the block being
// merged into the same type of block.
const blocksToMerge = (0,external_wp_blocks_namespaceObject.switchToBlockType)(blockToMerge, targetBlockName);
return blocksToMerge && blocksToMerge.length;
}
/**
* Get partial selected blocks with their content updated
* based on the selection.
*
* @param {Object} state Editor state.
*
* @return {Object[]} Updated partial selected blocks.
*/
const __unstableGetSelectedBlocksWithPartialSelection = state => {
const selectionAnchor = getSelectionStart(state);
const selectionFocus = getSelectionEnd(state);
if (selectionAnchor.clientId === selectionFocus.clientId) {
return selectors_EMPTY_ARRAY;
}
// Can't split if the selection is not set.
if (!selectionAnchor.attributeKey || !selectionFocus.attributeKey || typeof selectionAnchor.offset === 'undefined' || typeof selectionFocus.offset === 'undefined') {
return selectors_EMPTY_ARRAY;
}
const anchorRootClientId = getBlockRootClientId(state, selectionAnchor.clientId);
const focusRootClientId = getBlockRootClientId(state, selectionFocus.clientId);
// It's not splittable if the selection doesn't start and end in the same
// block list. Maybe in the future it should be allowed.
if (anchorRootClientId !== focusRootClientId) {
return selectors_EMPTY_ARRAY;
}
const blockOrder = getBlockOrder(state, anchorRootClientId);
const anchorIndex = blockOrder.indexOf(selectionAnchor.clientId);
const focusIndex = blockOrder.indexOf(selectionFocus.clientId);
// Reassign selection start and end based on order.
const [selectionStart, selectionEnd] = anchorIndex > focusIndex ? [selectionFocus, selectionAnchor] : [selectionAnchor, selectionFocus];
const blockA = getBlock(state, selectionStart.clientId);
const blockB = getBlock(state, selectionEnd.clientId);
const htmlA = blockA.attributes[selectionStart.attributeKey];
const htmlB = blockB.attributes[selectionEnd.attributeKey];
let valueA = (0,external_wp_richText_namespaceObject.create)({
html: htmlA
});
let valueB = (0,external_wp_richText_namespaceObject.create)({
html: htmlB
});
valueA = (0,external_wp_richText_namespaceObject.remove)(valueA, 0, selectionStart.offset);
valueB = (0,external_wp_richText_namespaceObject.remove)(valueB, selectionEnd.offset, valueB.text.length);
return [{
...blockA,
attributes: {
...blockA.attributes,
[selectionStart.attributeKey]: (0,external_wp_richText_namespaceObject.toHTMLString)({
value: valueA
})
}
}, {
...blockB,
attributes: {
...blockB.attributes,
[selectionEnd.attributeKey]: (0,external_wp_richText_namespaceObject.toHTMLString)({
value: valueB
})
}
}];
};
/**
* Returns an array containing all block client IDs in the editor in the order
* they appear. Optionally accepts a root client ID of the block list for which
* the order should be returned, defaulting to the top-level block order.
*
* @param {Object} state Editor state.
* @param {?string} rootClientId Optional root client ID of block list.
*
* @return {Array} Ordered client IDs of editor blocks.
*/
function getBlockOrder(state, rootClientId) {
return state.blocks.order.get(rootClientId || '') || selectors_EMPTY_ARRAY;
}
/**
* Returns the index at which the block corresponding to the specified client
* ID occurs within the block order, or `-1` if the block does not exist.
*
* @param {Object} state Editor state.
* @param {string} clientId Block client ID.
*
* @return {number} Index at which block exists in order.
*/
function getBlockIndex(state, clientId) {
const rootClientId = getBlockRootClientId(state, clientId);
return getBlockOrder(state, rootClientId).indexOf(clientId);
}
/**
* Returns true if the block corresponding to the specified client ID is
* currently selected and no multi-selection exists, or false otherwise.
*
* @param {Object} state Editor state.
* @param {string} clientId Block client ID.
*
* @return {boolean} Whether block is selected and multi-selection exists.
*/
function isBlockSelected(state, clientId) {
const {
selectionStart,
selectionEnd
} = state.selection;
if (selectionStart.clientId !== selectionEnd.clientId) {
return false;
}
return selectionStart.clientId === clientId;
}
/**
* Returns true if one of the block's inner blocks is selected.
*
* @param {Object} state Editor state.
* @param {string} clientId Block client ID.
* @param {boolean} deep Perform a deep check.
*
* @return {boolean} Whether the block has an inner block selected
*/
function hasSelectedInnerBlock(state, clientId, deep = false) {
const selectedBlockClientIds = getSelectedBlockClientIds(state);
if (!selectedBlockClientIds.length) {
return false;
}
if (deep) {
return selectedBlockClientIds.some(id =>
// Pass true because we don't care about order and it's more
// performant.
getBlockParents(state, id, true).includes(clientId));
}
return selectedBlockClientIds.some(id => getBlockRootClientId(state, id) === clientId);
}
/**
* Returns true if one of the block's inner blocks is dragged.
*
* @param {Object} state Editor state.
* @param {string} clientId Block client ID.
* @param {boolean} deep Perform a deep check.
*
* @return {boolean} Whether the block has an inner block dragged
*/
function hasDraggedInnerBlock(state, clientId, deep = false) {
return getBlockOrder(state, clientId).some(innerClientId => isBlockBeingDragged(state, innerClientId) || deep && hasDraggedInnerBlock(state, innerClientId, deep));
}
/**
* Returns true if the block corresponding to the specified client ID is
* currently selected but isn't the last of the selected blocks. Here "last"
* refers to the block sequence in the document, _not_ the sequence of
* multi-selection, which is why `state.selectionEnd` isn't used.
*
* @param {Object} state Editor state.
* @param {string} clientId Block client ID.
*
* @return {boolean} Whether block is selected and not the last in the
* selection.
*/
function isBlockWithinSelection(state, clientId) {
if (!clientId) {
return false;
}
const clientIds = getMultiSelectedBlockClientIds(state);
const index = clientIds.indexOf(clientId);
return index > -1 && index < clientIds.length - 1;
}
/**
* Returns true if a multi-selection has been made, or false otherwise.
*
* @param {Object} state Editor state.
*
* @return {boolean} Whether multi-selection has been made.
*/
function hasMultiSelection(state) {
const {
selectionStart,
selectionEnd
} = state.selection;
return selectionStart.clientId !== selectionEnd.clientId;
}
/**
* Whether in the process of multi-selecting or not. This flag is only true
* while the multi-selection is being selected (by mouse move), and is false
* once the multi-selection has been settled.
*
* @see hasMultiSelection
*
* @param {Object} state Global application state.
*
* @return {boolean} True if multi-selecting, false if not.
*/
function selectors_isMultiSelecting(state) {
return state.isMultiSelecting;
}
/**
* Selector that returns if multi-selection is enabled or not.
*
* @param {Object} state Global application state.
*
* @return {boolean} True if it should be possible to multi-select blocks, false if multi-selection is disabled.
*/
function selectors_isSelectionEnabled(state) {
return state.isSelectionEnabled;
}
/**
* Returns the block's editing mode, defaulting to "visual" if not explicitly
* assigned.
*
* @param {Object} state Editor state.
* @param {string} clientId Block client ID.
*
* @return {Object} Block editing mode.
*/
function getBlockMode(state, clientId) {
return state.blocksMode[clientId] || 'visual';
}
/**
* Returns true if the user is typing, or false otherwise.
*
* @param {Object} state Global application state.
*
* @return {boolean} Whether user is typing.
*/
function selectors_isTyping(state) {
return state.isTyping;
}
/**
* Returns true if the user is dragging blocks, or false otherwise.
*
* @param {Object} state Global application state.
*
* @return {boolean} Whether user is dragging blocks.
*/
function isDraggingBlocks(state) {
return !!state.draggedBlocks.length;
}
/**
* Returns the client ids of any blocks being directly dragged.
*
* This does not include children of a parent being dragged.
*
* @param {Object} state Global application state.
*
* @return {string[]} Array of dragged block client ids.
*/
function getDraggedBlockClientIds(state) {
return state.draggedBlocks;
}
/**
* Returns whether the block is being dragged.
*
* Only returns true if the block is being directly dragged,
* not if the block is a child of a parent being dragged.
* See `isAncestorBeingDragged` for child blocks.
*
* @param {Object} state Global application state.
* @param {string} clientId Client id for block to check.
*
* @return {boolean} Whether the block is being dragged.
*/
function isBlockBeingDragged(state, clientId) {
return state.draggedBlocks.includes(clientId);
}
/**
* Returns whether a parent/ancestor of the block is being dragged.
*
* @param {Object} state Global application state.
* @param {string} clientId Client id for block to check.
*
* @return {boolean} Whether the block's ancestor is being dragged.
*/
function isAncestorBeingDragged(state, clientId) {
// Return early if no blocks are being dragged rather than
// the more expensive check for parents.
if (!isDraggingBlocks(state)) {
return false;
}
const parents = getBlockParents(state, clientId);
return parents.some(parentClientId => isBlockBeingDragged(state, parentClientId));
}
/**
* Returns true if the caret is within formatted text, or false otherwise.
*
* @deprecated
*
* @return {boolean} Whether the caret is within formatted text.
*/
function isCaretWithinFormattedText() {
external_wp_deprecated_default()('wp.data.select( "core/block-editor" ).isCaretWithinFormattedText', {
since: '6.1',
version: '6.3'
});
return false;
}
/**
* Returns the location of the insertion cue. Defaults to the last index.
*
* @param {Object} state Editor state.
*
* @return {Object} Insertion point object with `rootClientId`, `index`.
*/
const getBlockInsertionPoint = (0,external_wp_data_namespaceObject.createSelector)(state => {
let rootClientId, index;
const {
insertionCue,
selection: {
selectionEnd
}
} = state;
if (insertionCue !== null) {
return insertionCue;
}
const {
clientId
} = selectionEnd;
if (clientId) {
rootClientId = getBlockRootClientId(state, clientId) || undefined;
index = getBlockIndex(state, selectionEnd.clientId) + 1;
} else {
index = getBlockOrder(state).length;
}
return {
rootClientId,
index
};
}, state => [state.insertionCue, state.selection.selectionEnd.clientId, state.blocks.parents, state.blocks.order]);
/**
* Returns true if the block insertion point is visible.
*
* @param {Object} state Global application state.
*
* @return {?boolean} Whether the insertion point is visible or not.
*/
function isBlockInsertionPointVisible(state) {
return state.insertionCue !== null;
}
/**
* Returns whether the blocks matches the template or not.
*
* @param {boolean} state
* @return {?boolean} Whether the template is valid or not.
*/
function isValidTemplate(state) {
return state.template.isValid;
}
/**
* Returns the defined block template
*
* @param {boolean} state
*
* @return {?Array} Block Template.
*/
function getTemplate(state) {
return state.settings.template;
}
/**
* Returns the defined block template lock. Optionally accepts a root block
* client ID as context, otherwise defaulting to the global context.
*
* @param {Object} state Editor state.
* @param {?string} rootClientId Optional block root client ID.
*
* @return {string|false} Block Template Lock
*/
function getTemplateLock(state, rootClientId) {
var _getBlockListSettings;
if (!rootClientId) {
var _state$settings$templ;
return (_state$settings$templ = state.settings.templateLock) !== null && _state$settings$templ !== void 0 ? _state$settings$templ : false;
}
return (_getBlockListSettings = getBlockListSettings(state, rootClientId)?.templateLock) !== null && _getBlockListSettings !== void 0 ? _getBlockListSettings : false;
}
/**
* Determines if the given block type is visible in the inserter.
* Note that this is different than whether a block is allowed to be inserted.
* In some cases, the block is not allowed in a given position but
* it should still be visible in the inserter to be able to add it
* to a different position.
*
* @param {Object} state Editor state.
* @param {string|Object} blockNameOrType The block type object, e.g., the response
* from the block directory; or a string name of
* an installed block type, e.g.' core/paragraph'.
* @param {?string} rootClientId Optional root client ID of block list.
*
* @return {boolean} Whether the given block type is allowed to be inserted.
*/
const isBlockVisibleInTheInserter = (state, blockNameOrType, rootClientId = null) => {
let blockType;
let blockName;
if (blockNameOrType && 'object' === typeof blockNameOrType) {
blockType = blockNameOrType;
blockName = blockNameOrType.name;
} else {
blockType = (0,external_wp_blocks_namespaceObject.getBlockType)(blockNameOrType);
blockName = blockNameOrType;
}
if (!blockType) {
return false;
}
const {
allowedBlockTypes
} = getSettings(state);
const isBlockAllowedInEditor = checkAllowList(allowedBlockTypes, blockName, true);
if (!isBlockAllowedInEditor) {
return false;
}
// If parent blocks are not visible, child blocks should be hidden too.
const parents = (Array.isArray(blockType.parent) ? blockType.parent : []).concat(Array.isArray(blockType.ancestor) ? blockType.ancestor : []);
if (parents.length > 0) {
// This is an exception to the rule that says that all blocks are visible in the inserter.
// Blocks that require a given parent or ancestor are only visible if we're within that parent.
if (parents.includes('core/post-content')) {
return true;
}
let current = rootClientId;
let hasParent = false;
do {
if (parents.includes(getBlockName(state, current))) {
hasParent = true;
break;
}
current = state.blocks.parents.get(current);
} while (current);
return hasParent;
}
return true;
};
/**
* Determines if the given block type is allowed to be inserted into the block list.
* This function is not exported and not memoized because using a memoized selector
* inside another memoized selector is just a waste of time.
*
* @param {Object} state Editor state.
* @param {string|Object} blockName The block type object, e.g., the response
* from the block directory; or a string name of
* an installed block type, e.g.' core/paragraph'.
* @param {?string} rootClientId Optional root client ID of block list.
*
* @return {boolean} Whether the given block type is allowed to be inserted.
*/
const canInsertBlockTypeUnmemoized = (state, blockName, rootClientId = null) => {
if (!isBlockVisibleInTheInserter(state, blockName, rootClientId)) {
return false;
}
let blockType;
if (blockName && 'object' === typeof blockName) {
blockType = blockName;
blockName = blockType.name;
} else {
blockType = (0,external_wp_blocks_namespaceObject.getBlockType)(blockName);
}
const isLocked = !!getTemplateLock(state, rootClientId);
if (isLocked) {
return false;
}
const _isSectionBlock = !!isSectionBlock(state, rootClientId);
if (_isSectionBlock) {
return false;
}
if (getBlockEditingMode(state, rootClientId !== null && rootClientId !== void 0 ? rootClientId : '') === 'disabled') {
return false;
}
const parentBlockListSettings = getBlockListSettings(state, rootClientId);
// The parent block doesn't have settings indicating it doesn't support
// inner blocks, return false.
if (rootClientId && parentBlockListSettings === undefined) {
return false;
}
const parentName = getBlockName(state, rootClientId);
const parentBlockType = (0,external_wp_blocks_namespaceObject.getBlockType)(parentName);
// Look at the `blockType.allowedBlocks` field to determine whether this is an allowed child block.
const parentAllowedChildBlocks = parentBlockType?.allowedBlocks;
let hasParentAllowedBlock = checkAllowList(parentAllowedChildBlocks, blockName);
// The `allowedBlocks` block list setting can further limit which blocks are allowed children.
if (hasParentAllowedBlock !== false) {
const parentAllowedBlocks = parentBlockListSettings?.allowedBlocks;
const hasParentListAllowedBlock = checkAllowList(parentAllowedBlocks, blockName);
// Never downgrade the result from `true` to `null`
if (hasParentListAllowedBlock !== null) {
hasParentAllowedBlock = hasParentListAllowedBlock;
}
}
const blockAllowedParentBlocks = blockType.parent;
const hasBlockAllowedParent = checkAllowList(blockAllowedParentBlocks, parentName);
let hasBlockAllowedAncestor = true;
const blockAllowedAncestorBlocks = blockType.ancestor;
if (blockAllowedAncestorBlocks) {
const ancestors = [rootClientId, ...getBlockParents(state, rootClientId)];
hasBlockAllowedAncestor = ancestors.some(ancestorClientId => checkAllowList(blockAllowedAncestorBlocks, getBlockName(state, ancestorClientId)));
}
const canInsert = hasBlockAllowedAncestor && (hasParentAllowedBlock === null && hasBlockAllowedParent === null || hasParentAllowedBlock === true || hasBlockAllowedParent === true);
if (!canInsert) {
return canInsert;
}
/**
* This filter is an ad-hoc solution to prevent adding template parts inside post content.
* Conceptually, having a filter inside a selector is bad pattern so this code will be
* replaced by a declarative API that doesn't the following drawbacks:
*
* Filters are not reactive: Upon switching between "template mode" and non "template mode",
* the filter and selector won't necessarily be executed again. For now, it doesn't matter much
* because you can't switch between the two modes while the inserter stays open.
*
* Filters are global: Once they're defined, they will affect all editor instances and all registries.
* An ideal API would only affect specific editor instances.
*/
return (0,external_wp_hooks_namespaceObject.applyFilters)('blockEditor.__unstableCanInsertBlockType', canInsert, blockType, rootClientId, {
// Pass bound selectors of the current registry. If we're in a nested
// context, the data will differ from the one selected from the root
// registry.
getBlock: getBlock.bind(null, state),
getBlockParentsByBlockName: getBlockParentsByBlockName.bind(null, state)
});
};
/**
* Determines if the given block type is allowed to be inserted into the block list.
*
* @param {Object} state Editor state.
* @param {string} blockName The name of the block type, e.g.' core/paragraph'.
* @param {?string} rootClientId Optional root client ID of block list.
*
* @return {boolean} Whether the given block type is allowed to be inserted.
*/
const canInsertBlockType = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => (0,external_wp_data_namespaceObject.createSelector)(canInsertBlockTypeUnmemoized, (state, blockName, rootClientId) => getInsertBlockTypeDependants(select)(state, rootClientId)));
/**
* Determines if the given blocks are allowed to be inserted into the block
* list.
*
* @param {Object} state Editor state.
* @param {string} clientIds The block client IDs to be inserted.
* @param {?string} rootClientId Optional root client ID of block list.
*
* @return {boolean} Whether the given blocks are allowed to be inserted.
*/
function canInsertBlocks(state, clientIds, rootClientId = null) {
return clientIds.every(id => canInsertBlockType(state, getBlockName(state, id), rootClientId));
}
/**
* Determines if the given block is allowed to be deleted.
*
* @param {Object} state Editor state.
* @param {string} clientId The block client Id.
*
* @return {boolean} Whether the given block is allowed to be removed.
*/
function canRemoveBlock(state, clientId) {
const attributes = getBlockAttributes(state, clientId);
if (attributes === null) {
return true;
}
if (attributes.lock?.remove !== undefined) {
return !attributes.lock.remove;
}
const rootClientId = getBlockRootClientId(state, clientId);
if (getTemplateLock(state, rootClientId)) {
return false;
}
const isBlockWithinSection = !!getParentSectionBlock(state, clientId);
if (isBlockWithinSection) {
return false;
}
return getBlockEditingMode(state, rootClientId) !== 'disabled';
}
/**
* Determines if the given blocks are allowed to be removed.
*
* @param {Object} state Editor state.
* @param {string} clientIds The block client IDs to be removed.
*
* @return {boolean} Whether the given blocks are allowed to be removed.
*/
function canRemoveBlocks(state, clientIds) {
return clientIds.every(clientId => canRemoveBlock(state, clientId));
}
/**
* Determines if the given block is allowed to be moved.
*
* @param {Object} state Editor state.
* @param {string} clientId The block client Id.
*
* @return {boolean} Whether the given block is allowed to be moved.
*/
function canMoveBlock(state, clientId) {
const attributes = getBlockAttributes(state, clientId);
if (attributes === null) {
return true;
}
if (attributes.lock?.move !== undefined) {
return !attributes.lock.move;
}
const rootClientId = getBlockRootClientId(state, clientId);
if (getTemplateLock(state, rootClientId) === 'all') {
return false;
}
return getBlockEditingMode(state, rootClientId) !== 'disabled';
}
/**
* Determines if the given blocks are allowed to be moved.
*
* @param {Object} state Editor state.
* @param {string} clientIds The block client IDs to be moved.
*
* @return {boolean} Whether the given blocks are allowed to be moved.
*/
function canMoveBlocks(state, clientIds) {
return clientIds.every(clientId => canMoveBlock(state, clientId));
}
/**
* Determines if the given block is allowed to be edited.
*
* @param {Object} state Editor state.
* @param {string} clientId The block client Id.
*
* @return {boolean} Whether the given block is allowed to be edited.
*/
function canEditBlock(state, clientId) {
const attributes = getBlockAttributes(state, clientId);
if (attributes === null) {
return true;
}
const {
lock
} = attributes;
// When the edit is true, we cannot edit the block.
return !lock?.edit;
}
/**
* Determines if the given block type can be locked/unlocked by a user.
*
* @param {Object} state Editor state.
* @param {(string|Object)} nameOrType Block name or type object.
*
* @return {boolean} Whether a given block type can be locked/unlocked.
*/
function canLockBlockType(state, nameOrType) {
if (!(0,external_wp_blocks_namespaceObject.hasBlockSupport)(nameOrType, 'lock', true)) {
return false;
}
// Use block editor settings as the default value.
return !!state.settings?.canLockBlocks;
}
/**
* Returns information about how recently and frequently a block has been inserted.
*
* @param {Object} state Global application state.
* @param {string} id A string which identifies the insert, e.g. 'core/block/12'
*
* @return {?{ time: number, count: number }} An object containing `time` which is when the last
* insert occurred as a UNIX epoch, and `count` which is
* the number of inserts that have occurred.
*/
function getInsertUsage(state, id) {
var _state$preferences$in;
return (_state$preferences$in = state.preferences.insertUsage?.[id]) !== null && _state$preferences$in !== void 0 ? _state$preferences$in : null;
}
/**
* Returns whether we can show a block type in the inserter
*
* @param {Object} state Global State
* @param {Object} blockType BlockType
* @param {?string} rootClientId Optional root client ID of block list.
*
* @return {boolean} Whether the given block type is allowed to be shown in the inserter.
*/
const canIncludeBlockTypeInInserter = (state, blockType, rootClientId) => {
if (!(0,external_wp_blocks_namespaceObject.hasBlockSupport)(blockType, 'inserter', true)) {
return false;
}
return canInsertBlockTypeUnmemoized(state, blockType.name, rootClientId);
};
/**
* Return a function to be used to transform a block variation to an inserter item
*
* @param {Object} state Global State
* @param {Object} item Denormalized inserter item
* @return {Function} Function to transform a block variation to inserter item
*/
const getItemFromVariation = (state, item) => variation => {
const variationId = `${item.id}/${variation.name}`;
const {
time,
count = 0
} = getInsertUsage(state, variationId) || {};
return {
...item,
id: variationId,
icon: variation.icon || item.icon,
title: variation.title || item.title,
description: variation.description || item.description,
category: variation.category || item.category,
// If `example` is explicitly undefined for the variation, the preview will not be shown.
example: variation.hasOwnProperty('example') ? variation.example : item.example,
initialAttributes: {
...item.initialAttributes,
...variation.attributes
},
innerBlocks: variation.innerBlocks,
keywords: variation.keywords || item.keywords,
frecency: calculateFrecency(time, count)
};
};
/**
* Returns the calculated frecency.
*
* 'frecency' is a heuristic (https://en.wikipedia.org/wiki/Frecency)
* that combines block usage frequency and recency.
*
* @param {number} time When the last insert occurred as a UNIX epoch
* @param {number} count The number of inserts that have occurred.
*
* @return {number} The calculated frecency.
*/
const calculateFrecency = (time, count) => {
if (!time) {
return count;
}
// The selector is cached, which means Date.now() is the last time that the
// relevant state changed. This suits our needs.
const duration = Date.now() - time;
switch (true) {
case duration < MILLISECONDS_PER_HOUR:
return count * 4;
case duration < MILLISECONDS_PER_DAY:
return count * 2;
case duration < MILLISECONDS_PER_WEEK:
return count / 2;
default:
return count / 4;
}
};
/**
* Returns a function that accepts a block type and builds an item to be shown
* in a specific context. It's used for building items for Inserter and available
* block Transforms list.
*
* @param {Object} state Editor state.
* @param {Object} options Options object for handling the building of a block type.
* @param {string} options.buildScope The scope for which the item is going to be used.
* @return {Function} Function returns an item to be shown in a specific context (Inserter|Transforms list).
*/
const buildBlockTypeItem = (state, {
buildScope = 'inserter'
}) => blockType => {
const id = blockType.name;
let isDisabled = false;
if (!(0,external_wp_blocks_namespaceObject.hasBlockSupport)(blockType.name, 'multiple', true)) {
isDisabled = getBlocksByClientId(state, getClientIdsWithDescendants(state)).some(({
name
}) => name === blockType.name);
}
const {
time,
count = 0
} = getInsertUsage(state, id) || {};
const blockItemBase = {
id,
name: blockType.name,
title: blockType.title,
icon: blockType.icon,
isDisabled,
frecency: calculateFrecency(time, count)
};
if (buildScope === 'transform') {
return blockItemBase;
}
const inserterVariations = (0,external_wp_blocks_namespaceObject.getBlockVariations)(blockType.name, 'inserter');
return {
...blockItemBase,
initialAttributes: {},
description: blockType.description,
category: blockType.category,
keywords: blockType.keywords,
parent: blockType.parent,
ancestor: blockType.ancestor,
variations: inserterVariations,
example: blockType.example,
utility: 1 // Deprecated.
};
};
/**
* Determines the items that appear in the inserter. Includes both static
* items (e.g. a regular block type) and dynamic items (e.g. a reusable block).
*
* Each item object contains what's necessary to display a button in the
* inserter and handle its selection.
*
* The 'frecency' property is a heuristic (https://en.wikipedia.org/wiki/Frecency)
* that combines block usage frequency and recency.
*
* Items are returned ordered descendingly by their 'utility' and 'frecency'.
*
* @param {Object} state Editor state.
* @param {?string} rootClientId Optional root client ID of block list.
*
* @return {WPEditorInserterItem[]} Items that appear in inserter.
*
* @typedef {Object} WPEditorInserterItem
* @property {string} id Unique identifier for the item.
* @property {string} name The type of block to create.
* @property {Object} initialAttributes Attributes to pass to the newly created block.
* @property {string} title Title of the item, as it appears in the inserter.
* @property {string} icon Dashicon for the item, as it appears in the inserter.
* @property {string} category Block category that the item is associated with.
* @property {string[]} keywords Keywords that can be searched to find this item.
* @property {boolean} isDisabled Whether or not the user should be prevented from inserting
* this item.
* @property {number} frecency Heuristic that combines frequency and recency.
*/
const getInserterItems = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => (0,external_wp_data_namespaceObject.createSelector)((state, rootClientId = null, options = DEFAULT_INSERTER_OPTIONS) => {
const buildReusableBlockInserterItem = reusableBlock => {
const icon = !reusableBlock.wp_pattern_sync_status ? {
src: library_symbol,
foreground: 'var(--wp-block-synced-color)'
} : library_symbol;
const id = `core/block/${reusableBlock.id}`;
const {
time,
count = 0
} = getInsertUsage(state, id) || {};
const frecency = calculateFrecency(time, count);
return {
id,
name: 'core/block',
initialAttributes: {
ref: reusableBlock.id
},
title: reusableBlock.title?.raw,
icon,
category: 'reusable',
keywords: ['reusable'],
isDisabled: false,
utility: 1,
// Deprecated.
frecency,
content: reusableBlock.content?.raw,
syncStatus: reusableBlock.wp_pattern_sync_status
};
};
const syncedPatternInserterItems = canInsertBlockTypeUnmemoized(state, 'core/block', rootClientId) ? unlock(select(STORE_NAME)).getReusableBlocks().map(buildReusableBlockInserterItem) : [];
const buildBlockTypeInserterItem = buildBlockTypeItem(state, {
buildScope: 'inserter'
});
let blockTypeInserterItems = (0,external_wp_blocks_namespaceObject.getBlockTypes)().filter(blockType => (0,external_wp_blocks_namespaceObject.hasBlockSupport)(blockType, 'inserter', true)).map(buildBlockTypeInserterItem);
if (options[isFiltered] !== false) {
blockTypeInserterItems = blockTypeInserterItems.filter(blockType => canIncludeBlockTypeInInserter(state, blockType, rootClientId));
} else {
blockTypeInserterItems = blockTypeInserterItems.filter(blockType => isBlockVisibleInTheInserter(state, blockType, rootClientId)).map(blockType => ({
...blockType,
isAllowedInCurrentRoot: canIncludeBlockTypeInInserter(state, blockType, rootClientId)
}));
}
const items = blockTypeInserterItems.reduce((accumulator, item) => {
const {
variations = []
} = item;
// Exclude any block type item that is to be replaced by a default variation.
if (!variations.some(({
isDefault
}) => isDefault)) {
accumulator.push(item);
}
if (variations.length) {
const variationMapper = getItemFromVariation(state, item);
accumulator.push(...variations.map(variationMapper));
}
return accumulator;
}, []);
// Ensure core blocks are prioritized in the returned results,
// because third party blocks can be registered earlier than
// the core blocks (usually by using the `init` action),
// thus affecting the display order.
// We don't sort reusable blocks as they are handled differently.
const groupByType = (blocks, block) => {
const {
core,
noncore
} = blocks;
const type = block.name.startsWith('core/') ? core : noncore;
type.push(block);
return blocks;
};
const {
core: coreItems,
noncore: nonCoreItems
} = items.reduce(groupByType, {
core: [],
noncore: []
});
const sortedBlockTypes = [...coreItems, ...nonCoreItems];
return [...sortedBlockTypes, ...syncedPatternInserterItems];
}, (state, rootClientId) => [(0,external_wp_blocks_namespaceObject.getBlockTypes)(), unlock(select(STORE_NAME)).getReusableBlocks(), state.blocks.order, state.preferences.insertUsage, ...getInsertBlockTypeDependants(select)(state, rootClientId)]));
/**
* Determines the items that appear in the available block transforms list.
*
* Each item object contains what's necessary to display a menu item in the
* transform list and handle its selection.
*
* The 'frecency' property is a heuristic (https://en.wikipedia.org/wiki/Frecency)
* that combines block usage frequency and recency.
*
* Items are returned ordered descendingly by their 'frecency'.
*
* @param {Object} state Editor state.
* @param {Object|Object[]} blocks Block object or array objects.
* @param {?string} rootClientId Optional root client ID of block list.
*
* @return {WPEditorTransformItem[]} Items that appear in inserter.
*
* @typedef {Object} WPEditorTransformItem
* @property {string} id Unique identifier for the item.
* @property {string} name The type of block to create.
* @property {string} title Title of the item, as it appears in the inserter.
* @property {string} icon Dashicon for the item, as it appears in the inserter.
* @property {boolean} isDisabled Whether or not the user should be prevented from inserting
* this item.
* @property {number} frecency Heuristic that combines frequency and recency.
*/
const getBlockTransformItems = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => (0,external_wp_data_namespaceObject.createSelector)((state, blocks, rootClientId = null) => {
const normalizedBlocks = Array.isArray(blocks) ? blocks : [blocks];
const buildBlockTypeTransformItem = buildBlockTypeItem(state, {
buildScope: 'transform'
});
const blockTypeTransformItems = (0,external_wp_blocks_namespaceObject.getBlockTypes)().filter(blockType => canIncludeBlockTypeInInserter(state, blockType, rootClientId)).map(buildBlockTypeTransformItem);
const itemsByName = Object.fromEntries(Object.entries(blockTypeTransformItems).map(([, value]) => [value.name, value]));
const possibleTransforms = (0,external_wp_blocks_namespaceObject.getPossibleBlockTransformations)(normalizedBlocks).reduce((accumulator, block) => {
if (itemsByName[block?.name]) {
accumulator.push(itemsByName[block.name]);
}
return accumulator;
}, []);
return orderBy(possibleTransforms, block => itemsByName[block.name].frecency, 'desc');
}, (state, blocks, rootClientId) => [(0,external_wp_blocks_namespaceObject.getBlockTypes)(), state.preferences.insertUsage, ...getInsertBlockTypeDependants(select)(state, rootClientId)]));
/**
* Determines whether there are items to show in the inserter.
*
* @param {Object} state Editor state.
* @param {?string} rootClientId Optional root client ID of block list.
*
* @return {boolean} Items that appear in inserter.
*/
const hasInserterItems = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => (state, rootClientId = null) => {
const hasBlockType = (0,external_wp_blocks_namespaceObject.getBlockTypes)().some(blockType => canIncludeBlockTypeInInserter(state, blockType, rootClientId));
if (hasBlockType) {
return true;
}
const hasReusableBlock = canInsertBlockTypeUnmemoized(state, 'core/block', rootClientId) && unlock(select(STORE_NAME)).getReusableBlocks().length > 0;
return hasReusableBlock;
});
/**
* Returns the list of allowed inserter blocks for inner blocks children.
*
* @param {Object} state Editor state.
* @param {?string} rootClientId Optional root client ID of block list.
*
* @return {Array?} The list of allowed block types.
*/
const getAllowedBlocks = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => (0,external_wp_data_namespaceObject.createSelector)((state, rootClientId = null) => {
if (!rootClientId) {
return;
}
const blockTypes = (0,external_wp_blocks_namespaceObject.getBlockTypes)().filter(blockType => canIncludeBlockTypeInInserter(state, blockType, rootClientId));
const hasReusableBlock = canInsertBlockTypeUnmemoized(state, 'core/block', rootClientId) && unlock(select(STORE_NAME)).getReusableBlocks().length > 0;
if (hasReusableBlock) {
blockTypes.push('core/block');
}
return blockTypes;
}, (state, rootClientId) => [(0,external_wp_blocks_namespaceObject.getBlockTypes)(), unlock(select(STORE_NAME)).getReusableBlocks(), ...getInsertBlockTypeDependants(select)(state, rootClientId)]));
const __experimentalGetAllowedBlocks = (0,external_wp_data_namespaceObject.createSelector)((state, rootClientId = null) => {
external_wp_deprecated_default()('wp.data.select( "core/block-editor" ).__experimentalGetAllowedBlocks', {
alternative: 'wp.data.select( "core/block-editor" ).getAllowedBlocks',
since: '6.2',
version: '6.4'
});
return getAllowedBlocks(state, rootClientId);
}, (state, rootClientId) => getAllowedBlocks.getDependants(state, rootClientId));
/**
* Returns the block to be directly inserted by the block appender.
*
* @param {Object} state Editor state.
* @param {?string} rootClientId Optional root client ID of block list.
*
* @return {WPDirectInsertBlock|undefined} The block type to be directly inserted.
*
* @typedef {Object} WPDirectInsertBlock
* @property {string} name The type of block.
* @property {?Object} attributes Attributes to pass to the newly created block.
* @property {?Array<string>} attributesToCopy Attributes to be copied from adjacent blocks when inserted.
*/
function getDirectInsertBlock(state, rootClientId = null) {
var _state$blockListSetti;
if (!rootClientId) {
return;
}
const {
defaultBlock,
directInsert
} = (_state$blockListSetti = state.blockListSettings[rootClientId]) !== null && _state$blockListSetti !== void 0 ? _state$blockListSetti : {};
if (!defaultBlock || !directInsert) {
return;
}
return defaultBlock;
}
function __experimentalGetDirectInsertBlock(state, rootClientId = null) {
external_wp_deprecated_default()('wp.data.select( "core/block-editor" ).__experimentalGetDirectInsertBlock', {
alternative: 'wp.data.select( "core/block-editor" ).getDirectInsertBlock',
since: '6.3',
version: '6.4'
});
return getDirectInsertBlock(state, rootClientId);
}
const __experimentalGetParsedPattern = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => (state, patternName) => {
const pattern = unlock(select(STORE_NAME)).getPatternBySlug(patternName);
return pattern ? getParsedPattern(pattern) : null;
});
const getAllowedPatternsDependants = select => (state, rootClientId) => [...getAllPatternsDependants(select)(state), ...getInsertBlockTypeDependants(select)(state, rootClientId)];
const patternsWithParsedBlocks = new WeakMap();
function enhancePatternWithParsedBlocks(pattern) {
let enhancedPattern = patternsWithParsedBlocks.get(pattern);
if (!enhancedPattern) {
enhancedPattern = {
...pattern,
get blocks() {
return getParsedPattern(pattern).blocks;
}
};
patternsWithParsedBlocks.set(pattern, enhancedPattern);
}
return enhancedPattern;
}
/**
* Returns the list of allowed patterns for inner blocks children.
*
* @param {Object} state Editor state.
* @param {?string} rootClientId Optional target root client ID.
*
* @return {Array?} The list of allowed patterns.
*/
const __experimentalGetAllowedPatterns = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => {
return (0,external_wp_data_namespaceObject.createSelector)((state, rootClientId = null, options = DEFAULT_INSERTER_OPTIONS) => {
const {
getAllPatterns
} = unlock(select(STORE_NAME));
const patterns = getAllPatterns();
const {
allowedBlockTypes
} = getSettings(state);
const parsedPatterns = patterns.filter(({
inserter = true
}) => !!inserter).map(enhancePatternWithParsedBlocks);
const availableParsedPatterns = parsedPatterns.filter(pattern => checkAllowListRecursive(getGrammar(pattern), allowedBlockTypes));
const patternsAllowed = availableParsedPatterns.filter(pattern => getGrammar(pattern).every(({
blockName: name
}) => options[isFiltered] !== false ? canInsertBlockType(state, name, rootClientId) : isBlockVisibleInTheInserter(state, name, rootClientId)));
return patternsAllowed;
}, getAllowedPatternsDependants(select));
});
/**
* Returns the list of patterns based on their declared `blockTypes`
* and a block's name.
* Patterns can use `blockTypes` to integrate in work flows like
* suggesting appropriate patterns in a Placeholder state(during insertion)
* or blocks transformations.
*
* @param {Object} state Editor state.
* @param {string|string[]} blockNames Block's name or array of block names to find matching patterns.
* @param {?string} rootClientId Optional target root client ID.
*
* @return {Array} The list of matched block patterns based on declared `blockTypes` and block name.
*/
const getPatternsByBlockTypes = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => (0,external_wp_data_namespaceObject.createSelector)((state, blockNames, rootClientId = null) => {
if (!blockNames) {
return selectors_EMPTY_ARRAY;
}
const patterns = select(STORE_NAME).__experimentalGetAllowedPatterns(rootClientId);
const normalizedBlockNames = Array.isArray(blockNames) ? blockNames : [blockNames];
const filteredPatterns = patterns.filter(pattern => pattern?.blockTypes?.some?.(blockName => normalizedBlockNames.includes(blockName)));
if (filteredPatterns.length === 0) {
return selectors_EMPTY_ARRAY;
}
return filteredPatterns;
}, (state, blockNames, rootClientId) => getAllowedPatternsDependants(select)(state, rootClientId)));
const __experimentalGetPatternsByBlockTypes = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => {
external_wp_deprecated_default()('wp.data.select( "core/block-editor" ).__experimentalGetPatternsByBlockTypes', {
alternative: 'wp.data.select( "core/block-editor" ).getPatternsByBlockTypes',
since: '6.2',
version: '6.4'
});
return select(STORE_NAME).getPatternsByBlockTypes;
});
/**
* Determines the items that appear in the available pattern transforms list.
*
* For now we only handle blocks without InnerBlocks and take into account
* the `role` property of blocks' attributes for the transformation.
*
* We return the first set of possible eligible block patterns,
* by checking the `blockTypes` property. We still have to recurse through
* block pattern's blocks and try to find matches from the selected blocks.
* Now this happens in the consumer to avoid heavy operations in the selector.
*
* @param {Object} state Editor state.
* @param {Object[]} blocks The selected blocks.
* @param {?string} rootClientId Optional root client ID of block list.
*
* @return {WPBlockPattern[]} Items that are eligible for a pattern transformation.
*/
const __experimentalGetPatternTransformItems = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => (0,external_wp_data_namespaceObject.createSelector)((state, blocks, rootClientId = null) => {
if (!blocks) {
return selectors_EMPTY_ARRAY;
}
/**
* For now we only handle blocks without InnerBlocks and take into account
* the `role` property of blocks' attributes for the transformation.
* Note that the blocks have been retrieved through `getBlock`, which doesn't
* return the inner blocks of an inner block controller, so we still need
* to check for this case too.
*/
if (blocks.some(({
clientId,
innerBlocks
}) => innerBlocks.length || areInnerBlocksControlled(state, clientId))) {
return selectors_EMPTY_ARRAY;
}
// Create a Set of the selected block names that is used in patterns filtering.
const selectedBlockNames = Array.from(new Set(blocks.map(({
name
}) => name)));
/**
* Here we will return first set of possible eligible block patterns,
* by checking the `blockTypes` property. We still have to recurse through
* block pattern's blocks and try to find matches from the selected blocks.
* Now this happens in the consumer to avoid heavy operations in the selector.
*/
return select(STORE_NAME).getPatternsByBlockTypes(selectedBlockNames, rootClientId);
}, (state, blocks, rootClientId) => getAllowedPatternsDependants(select)(state, rootClientId)));
/**
* Returns the Block List settings of a block, if any exist.
*
* @param {Object} state Editor state.
* @param {?string} clientId Block client ID.
*
* @return {?Object} Block settings of the block if set.
*/
function getBlockListSettings(state, clientId) {
return state.blockListSettings[clientId];
}
/**
* Returns the editor settings.
*
* @param {Object} state Editor state.
*
* @return {Object} The editor settings object.
*/
function getSettings(state) {
return state.settings;
}
/**
* Returns true if the most recent block change is be considered persistent, or
* false otherwise. A persistent change is one committed by BlockEditorProvider
* via its `onChange` callback, in addition to `onInput`.
*
* @param {Object} state Block editor state.
*
* @return {boolean} Whether the most recent block change was persistent.
*/
function isLastBlockChangePersistent(state) {
return state.blocks.isPersistentChange;
}
/**
* Returns the block list settings for an array of blocks, if any exist.
*
* @param {Object} state Editor state.
* @param {Array} clientIds Block client IDs.
*
* @return {Object} An object where the keys are client ids and the values are
* a block list setting object.
*/
const __experimentalGetBlockListSettingsForBlocks = (0,external_wp_data_namespaceObject.createSelector)((state, clientIds = []) => {
return clientIds.reduce((blockListSettingsForBlocks, clientId) => {
if (!state.blockListSettings[clientId]) {
return blockListSettingsForBlocks;
}
return {
...blockListSettingsForBlocks,
[clientId]: state.blockListSettings[clientId]
};
}, {});
}, state => [state.blockListSettings]);
/**
* Returns the title of a given reusable block
*
* @param {Object} state Global application state.
* @param {number|string} ref The shared block's ID.
*
* @return {string} The reusable block saved title.
*/
const __experimentalGetReusableBlockTitle = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => (0,external_wp_data_namespaceObject.createSelector)((state, ref) => {
external_wp_deprecated_default()("wp.data.select( 'core/block-editor' ).__experimentalGetReusableBlockTitle", {
since: '6.6',
version: '6.8'
});
const reusableBlock = unlock(select(STORE_NAME)).getReusableBlocks().find(block => block.id === ref);
if (!reusableBlock) {
return null;
}
return reusableBlock.title?.raw;
}, () => [unlock(select(STORE_NAME)).getReusableBlocks()]));
/**
* Returns true if the most recent block change is be considered ignored, or
* false otherwise. An ignored change is one not to be committed by
* BlockEditorProvider, neither via `onChange` nor `onInput`.
*
* @param {Object} state Block editor state.
*
* @return {boolean} Whether the most recent block change was ignored.
*/
function __unstableIsLastBlockChangeIgnored(state) {
// TODO: Removal Plan: Changes incurred by RECEIVE_BLOCKS should not be
// ignored if in-fact they result in a change in blocks state. The current
// need to ignore changes not a result of user interaction should be
// accounted for in the refactoring of reusable blocks as occurring within
// their own separate block editor / state (#7119).
return state.blocks.isIgnoredChange;
}
/**
* Returns the block attributes changed as a result of the last dispatched
* action.
*
* @param {Object} state Block editor state.
*
* @return {Object<string,Object>} Subsets of block attributes changed, keyed
* by block client ID.
*/
function __experimentalGetLastBlockAttributeChanges(state) {
return state.lastBlockAttributesChange;
}
/**
* Returns whether the navigation mode is enabled.
*
* @param {Object} state Editor state.
*
* @return {boolean} Is navigation mode enabled.
*/
function isNavigationMode(state) {
return __unstableGetEditorMode(state) === 'navigation';
}
/**
* Returns the current editor mode.
*
* @param {Object} state Editor state.
*
* @return {string} the editor mode.
*/
const __unstableGetEditorMode = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => state => {
var _state$settings$edito;
if (!window?.__experimentalEditorWriteMode) {
return 'edit';
}
return (_state$settings$edito = state.settings.editorTool) !== null && _state$settings$edito !== void 0 ? _state$settings$edito : select(external_wp_preferences_namespaceObject.store).get('core', 'editorTool');
});
/**
* Returns whether block moving mode is enabled.
*
* @deprecated
*/
function hasBlockMovingClientId() {
external_wp_deprecated_default()('wp.data.select( "core/block-editor" ).hasBlockMovingClientId', {
since: '6.7',
hint: 'Block moving mode feature has been removed'
});
return false;
}
/**
* Returns true if the last change was an automatic change, false otherwise.
*
* @param {Object} state Global application state.
*
* @return {boolean} Whether the last change was automatic.
*/
function didAutomaticChange(state) {
return !!state.automaticChangeStatus;
}
/**
* Returns true if the current highlighted block matches the block clientId.
*
* @param {Object} state Global application state.
* @param {string} clientId The block to check.
*
* @return {boolean} Whether the block is currently highlighted.
*/
function isBlockHighlighted(state, clientId) {
return state.highlightedBlock === clientId;
}
/**
* Checks if a given block has controlled inner blocks.
*
* @param {Object} state Global application state.
* @param {string} clientId The block to check.
*
* @return {boolean} True if the block has controlled inner blocks.
*/
function areInnerBlocksControlled(state, clientId) {
return !!state.blocks.controlledInnerBlocks[clientId];
}
/**
* Returns the clientId for the first 'active' block of a given array of block names.
* A block is 'active' if it (or a child) is the selected block.
* Returns the first match moving up the DOM from the selected block.
*
* @param {Object} state Global application state.
* @param {string[]} validBlocksNames The names of block types to check for.
*
* @return {string} The matching block's clientId.
*/
const __experimentalGetActiveBlockIdByBlockNames = (0,external_wp_data_namespaceObject.createSelector)((state, validBlockNames) => {
if (!validBlockNames.length) {
return null;
}
// Check if selected block is a valid entity area.
const selectedBlockClientId = getSelectedBlockClientId(state);
if (validBlockNames.includes(getBlockName(state, selectedBlockClientId))) {
return selectedBlockClientId;
}
// Check if first selected block is a child of a valid entity area.
const multiSelectedBlockClientIds = getMultiSelectedBlockClientIds(state);
const entityAreaParents = getBlockParentsByBlockName(state, selectedBlockClientId || multiSelectedBlockClientIds[0], validBlockNames);
if (entityAreaParents) {
// Last parent closest/most interior.
return entityAreaParents[entityAreaParents.length - 1];
}
return null;
}, (state, validBlockNames) => [state.selection.selectionStart.clientId, state.selection.selectionEnd.clientId, validBlockNames]);
/**
* Tells if the block with the passed clientId was just inserted.
*
* @param {Object} state Global application state.
* @param {Object} clientId Client Id of the block.
* @param {?string} source Optional insertion source of the block.
* @return {boolean} True if the block matches the last block inserted from the specified source.
*/
function wasBlockJustInserted(state, clientId, source) {
const {
lastBlockInserted
} = state;
return lastBlockInserted.clientIds?.includes(clientId) && lastBlockInserted.source === source;
}
/**
* Tells if the block is visible on the canvas or not.
*
* @param {Object} state Global application state.
* @param {Object} clientId Client Id of the block.
* @return {boolean} True if the block is visible.
*/
function isBlockVisible(state, clientId) {
var _state$blockVisibilit;
return (_state$blockVisibilit = state.blockVisibility?.[clientId]) !== null && _state$blockVisibilit !== void 0 ? _state$blockVisibilit : true;
}
/**
* Returns the currently hovered block.
*
* @param {Object} state Global application state.
* @return {Object} Client Id of the hovered block.
*/
function getHoveredBlockClientId(state) {
return state.hoveredBlockClientId;
}
/**
* Returns the list of all hidden blocks.
*
* @param {Object} state Global application state.
* @return {[string]} List of hidden blocks.
*/
const __unstableGetVisibleBlocks = (0,external_wp_data_namespaceObject.createSelector)(state => {
const visibleBlocks = new Set(Object.keys(state.blockVisibility).filter(key => state.blockVisibility[key]));
if (visibleBlocks.size === 0) {
return EMPTY_SET;
}
return visibleBlocks;
}, state => [state.blockVisibility]);
function __unstableHasActiveBlockOverlayActive(state, clientId) {
// Prevent overlay on blocks with a non-default editing mode. If the mode is
// 'disabled' then the overlay is redundant since the block can't be
// selected. If the mode is 'contentOnly' then the overlay is redundant
// since there will be no controls to interact with once selected.
if (getBlockEditingMode(state, clientId) !== 'default') {
return false;
}
// If the block editing is locked, the block overlay is always active.
if (!canEditBlock(state, clientId)) {
return true;
}
// In zoom-out mode, the block overlay is always active for section level blocks.
if (isZoomOut(state)) {
const sectionRootClientId = getSectionRootClientId(state);
if (sectionRootClientId) {
const sectionClientIds = getBlockOrder(state, sectionRootClientId);
if (sectionClientIds?.includes(clientId)) {
return true;
}
} else if (clientId && !getBlockRootClientId(state, clientId)) {
return true;
}
}
// In navigation mode, the block overlay is active when the block is not
// selected (and doesn't contain a selected child). The same behavior is
// also enabled in all modes for blocks that have controlled children
// (reusable block, template part, navigation), unless explicitly disabled
// with `supports.__experimentalDisableBlockOverlay`.
const blockSupportDisable = (0,external_wp_blocks_namespaceObject.hasBlockSupport)(getBlockName(state, clientId), '__experimentalDisableBlockOverlay', false);
const shouldEnableIfUnselected = blockSupportDisable ? false : areInnerBlocksControlled(state, clientId);
return shouldEnableIfUnselected && !isBlockSelected(state, clientId) && !hasSelectedInnerBlock(state, clientId, true);
}
function __unstableIsWithinBlockOverlay(state, clientId) {
let parent = state.blocks.parents.get(clientId);
while (!!parent) {
if (__unstableHasActiveBlockOverlayActive(state, parent)) {
return true;
}
parent = state.blocks.parents.get(parent);
}
return false;
}
/**
* @typedef {import('../components/block-editing-mode').BlockEditingMode} BlockEditingMode
*/
/**
* Returns the block editing mode for a given block.
*
* The mode can be one of three options:
*
* - `'disabled'`: Prevents editing the block entirely, i.e. it cannot be
* selected.
* - `'contentOnly'`: Hides all non-content UI, e.g. auxiliary controls in the
* toolbar, the block movers, block settings.
* - `'default'`: Allows editing the block as normal.
*
* Blocks can set a mode using the `useBlockEditingMode` hook.
*
* The mode is inherited by all of the block's inner blocks, unless they have
* their own mode.
*
* A template lock can also set a mode. If the template lock is `'contentOnly'`,
* the block's mode is overridden to `'contentOnly'` if the block has a content
* role attribute, or `'disabled'` otherwise.
*
* @see useBlockEditingMode
*
* @param {Object} state Global application state.
* @param {string} clientId The block client ID, or `''` for the root container.
*
* @return {BlockEditingMode} The block editing mode. One of `'disabled'`,
* `'contentOnly'`, or `'default'`.
*/
const getBlockEditingMode = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => (state, clientId = '') => {
// Some selectors that call this provide `null` as the default
// rootClientId, but the default rootClientId is actually `''`.
if (clientId === null) {
clientId = '';
}
const isNavMode = isNavigationMode(state);
// If the editor is currently not in navigation mode, check if the clientId
// has an editing mode set in the regular derived map.
// There may be an editing mode set here for synced patterns or in zoomed out
// mode.
if (!isNavMode && state.derivedBlockEditingModes?.has(clientId)) {
return state.derivedBlockEditingModes.get(clientId);
}
// If the editor *is* in navigation mode, the block editing mode states
// are stored in the derivedNavModeBlockEditingModes map.
if (isNavMode && state.derivedNavModeBlockEditingModes?.has(clientId)) {
return state.derivedNavModeBlockEditingModes.get(clientId);
}
// In normal mode, consider that an explicitly set editing mode takes over.
const blockEditingMode = state.blockEditingModes.get(clientId);
if (blockEditingMode) {
return blockEditingMode;
}
// In normal mode, top level is default mode.
if (clientId === '') {
return 'default';
}
const rootClientId = getBlockRootClientId(state, clientId);
const templateLock = getTemplateLock(state, rootClientId);
// If the parent of the block is contentOnly locked, check whether it's a content block.
if (templateLock === 'contentOnly') {
const name = getBlockName(state, clientId);
const {
hasContentRoleAttribute
} = unlock(select(external_wp_blocks_namespaceObject.store));
const isContent = hasContentRoleAttribute(name);
return isContent ? 'contentOnly' : 'disabled';
}
return 'default';
});
/**
* Indicates if a block is ungroupable.
* A block is ungroupable if it is a single grouping block with inner blocks.
* If a block has an `ungroup` transform, it is also ungroupable, without the
* requirement of being the default grouping block.
* Additionally a block can only be ungrouped if it has inner blocks and can
* be removed.
*
* @param {Object} state Global application state.
* @param {string} clientId Client Id of the block. If not passed the selected block's client id will be used.
* @return {boolean} True if the block is ungroupable.
*/
const isUngroupable = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => (state, clientId = '') => {
const _clientId = clientId || getSelectedBlockClientId(state);
if (!_clientId) {
return false;
}
const {
getGroupingBlockName
} = select(external_wp_blocks_namespaceObject.store);
const block = getBlock(state, _clientId);
const groupingBlockName = getGroupingBlockName();
const _isUngroupable = block && (block.name === groupingBlockName || (0,external_wp_blocks_namespaceObject.getBlockType)(block.name)?.transforms?.ungroup) && !!block.innerBlocks.length;
return _isUngroupable && canRemoveBlock(state, _clientId);
});
/**
* Indicates if the provided blocks(by client ids) are groupable.
* We need to have at least one block, have a grouping block name set and
* be able to remove these blocks.
*
* @param {Object} state Global application state.
* @param {string[]} clientIds Block client ids. If not passed the selected blocks client ids will be used.
* @return {boolean} True if the blocks are groupable.
*/
const isGroupable = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => (state, clientIds = selectors_EMPTY_ARRAY) => {
const {
getGroupingBlockName
} = select(external_wp_blocks_namespaceObject.store);
const groupingBlockName = getGroupingBlockName();
const _clientIds = clientIds?.length ? clientIds : getSelectedBlockClientIds(state);
const rootClientId = _clientIds?.length ? getBlockRootClientId(state, _clientIds[0]) : undefined;
const groupingBlockAvailable = canInsertBlockType(state, groupingBlockName, rootClientId);
const _isGroupable = groupingBlockAvailable && _clientIds.length;
return _isGroupable && canRemoveBlocks(state, _clientIds);
});
/**
* DO-NOT-USE in production.
* This selector is created for internal/experimental only usage and may be
* removed anytime without any warning, causing breakage on any plugin or theme invoking it.
*
* @deprecated
*
* @param {Object} state Global application state.
* @param {Object} clientId Client Id of the block.
*
* @return {?string} Client ID of the ancestor block that is content locking the block.
*/
const __unstableGetContentLockingParent = (state, clientId) => {
external_wp_deprecated_default()("wp.data.select( 'core/block-editor' ).__unstableGetContentLockingParent", {
since: '6.1',
version: '6.7'
});
return getContentLockingParent(state, clientId);
};
/**
* DO-NOT-USE in production.
* This selector is created for internal/experimental only usage and may be
* removed anytime without any warning, causing breakage on any plugin or theme invoking it.
*
* @deprecated
*
* @param {Object} state Global application state.
*/
function __unstableGetTemporarilyEditingAsBlocks(state) {
external_wp_deprecated_default()("wp.data.select( 'core/block-editor' ).__unstableGetTemporarilyEditingAsBlocks", {
since: '6.1',
version: '6.7'
});
return getTemporarilyEditingAsBlocks(state);
}
/**
* DO-NOT-USE in production.
* This selector is created for internal/experimental only usage and may be
* removed anytime without any warning, causing breakage on any plugin or theme invoking it.
*
* @deprecated
*
* @param {Object} state Global application state.
*/
function __unstableGetTemporarilyEditingFocusModeToRevert(state) {
external_wp_deprecated_default()("wp.data.select( 'core/block-editor' ).__unstableGetTemporarilyEditingFocusModeToRevert", {
since: '6.5',
version: '6.7'
});
return getTemporarilyEditingFocusModeToRevert(state);
}
;// external ["wp","a11y"]
const external_wp_a11y_namespaceObject = window["wp"]["a11y"];
;// ./node_modules/@wordpress/block-editor/build-module/store/private-actions.js
/**
* WordPress dependencies
*/
/**
* Internal dependencies
*/
const castArray = maybeArray => Array.isArray(maybeArray) ? maybeArray : [maybeArray];
/**
* A list of private/experimental block editor settings that
* should not become a part of the WordPress public API.
* BlockEditorProvider will remove these settings from the
* settings object it receives.
*
* @see https://github.com/WordPress/gutenberg/pull/46131
*/
const privateSettings = ['inserterMediaCategories', 'blockInspectorAnimation', 'mediaSideload'];
/**
* Action that updates the block editor settings and
* conditionally preserves the experimental ones.
*
* @param {Object} settings Updated settings
* @param {Object} options Options object.
* @param {boolean} options.stripExperimentalSettings Whether to strip experimental settings.
* @param {boolean} options.reset Whether to reset the settings.
* @return {Object} Action object
*/
function __experimentalUpdateSettings(settings, {
stripExperimentalSettings = false,
reset = false
} = {}) {
let incomingSettings = settings;
if (Object.hasOwn(incomingSettings, '__unstableIsPreviewMode')) {
external_wp_deprecated_default()("__unstableIsPreviewMode argument in wp.data.dispatch('core/block-editor').updateSettings", {
since: '6.8',
alternative: 'isPreviewMode'
});
incomingSettings = {
...incomingSettings
};
incomingSettings.isPreviewMode = incomingSettings.__unstableIsPreviewMode;
delete incomingSettings.__unstableIsPreviewMode;
}
let cleanSettings = incomingSettings;
// There are no plugins in the mobile apps, so there is no
// need to strip the experimental settings:
if (stripExperimentalSettings && external_wp_element_namespaceObject.Platform.OS === 'web') {
cleanSettings = {};
for (const key in incomingSettings) {
if (!privateSettings.includes(key)) {
cleanSettings[key] = incomingSettings[key];
}
}
}
return {
type: 'UPDATE_SETTINGS',
settings: cleanSettings,
reset
};
}
/**
* Hides the block interface (eg. toolbar, outline, etc.)
*
* @return {Object} Action object.
*/
function hideBlockInterface() {
return {
type: 'HIDE_BLOCK_INTERFACE'
};
}
/**
* Shows the block interface (eg. toolbar, outline, etc.)
*
* @return {Object} Action object.
*/
function showBlockInterface() {
return {
type: 'SHOW_BLOCK_INTERFACE'
};
}
/**
* Yields action objects used in signalling that the blocks corresponding to
* the set of specified client IDs are to be removed.
*
* Compared to `removeBlocks`, this private interface exposes an additional
* parameter; see `forceRemove`.
*
* @param {string|string[]} clientIds Client IDs of blocks to remove.
* @param {boolean} selectPrevious True if the previous block
* or the immediate parent
* (if no previous block exists)
* should be selected
* when a block is removed.
* @param {boolean} forceRemove Whether to force the operation,
* bypassing any checks for certain
* block types.
*/
const privateRemoveBlocks = (clientIds, selectPrevious = true, forceRemove = false) => ({
select,
dispatch,
registry
}) => {
if (!clientIds || !clientIds.length) {
return;
}
clientIds = castArray(clientIds);
const canRemoveBlocks = select.canRemoveBlocks(clientIds);
if (!canRemoveBlocks) {
return;
}
// In certain editing contexts, we'd like to prevent accidental removal
// of important blocks. For example, in the site editor, the Query Loop
// block is deemed important. In such cases, we'll ask the user for
// confirmation that they intended to remove such block(s). However,
// the editor instance is responsible for presenting those confirmation
// prompts to the user. Any instance opting into removal prompts must
// register using `setBlockRemovalRules()`.
//
// @see https://github.com/WordPress/gutenberg/pull/51145
const rules = !forceRemove && select.getBlockRemovalRules();
if (rules) {
function flattenBlocks(blocks) {
const result = [];
const stack = [...blocks];
while (stack.length) {
const {
innerBlocks,
...block
} = stack.shift();
stack.push(...innerBlocks);
result.push(block);
}
return result;
}
const blockList = clientIds.map(select.getBlock);
const flattenedBlocks = flattenBlocks(blockList);
// Find the first message and use it.
let message;
for (const rule of rules) {
message = rule.callback(flattenedBlocks);
if (message) {
dispatch(displayBlockRemovalPrompt(clientIds, selectPrevious, message));
return;
}
}
}
if (selectPrevious) {
dispatch.selectPreviousBlock(clientIds[0], selectPrevious);
}
// We're batching these two actions because an extra `undo/redo` step can
// be created, based on whether we insert a default block or not.
registry.batch(() => {
dispatch({
type: 'REMOVE_BLOCKS',
clientIds
});
// To avoid a focus loss when removing the last block, assure there is
// always a default block if the last of the blocks have been removed.
dispatch(ensureDefaultBlock());
});
};
/**
* Action which will insert a default block insert action if there
* are no other blocks at the root of the editor. This action should be used
* in actions which may result in no blocks remaining in the editor (removal,
* replacement, etc).
*/
const ensureDefaultBlock = () => ({
select,
dispatch
}) => {
// To avoid a focus loss when removing the last block, assure there is
// always a default block if the last of the blocks have been removed.
const count = select.getBlockCount();
if (count > 0) {
return;
}
// If there's an custom appender, don't insert default block.
// We have to remember to manually move the focus elsewhere to
// prevent it from being lost though.
const {
__unstableHasCustomAppender
} = select.getSettings();
if (__unstableHasCustomAppender) {
return;
}
dispatch.insertDefaultBlock();
};
/**
* Returns an action object used in signalling that a block removal prompt must
* be displayed.
*
* Contrast with `setBlockRemovalRules`.
*
* @param {string|string[]} clientIds Client IDs of blocks to remove.
* @param {boolean} selectPrevious True if the previous block or the
* immediate parent (if no previous
* block exists) should be selected
* when a block is removed.
* @param {string} message Message to display in the prompt.
*
* @return {Object} Action object.
*/
function displayBlockRemovalPrompt(clientIds, selectPrevious, message) {
return {
type: 'DISPLAY_BLOCK_REMOVAL_PROMPT',
clientIds,
selectPrevious,
message
};
}
/**
* Returns an action object used in signalling that a block removal prompt must
* be cleared, either be cause the user has confirmed or canceled the request
* for removal.
*
* @return {Object} Action object.
*/
function clearBlockRemovalPrompt() {
return {
type: 'CLEAR_BLOCK_REMOVAL_PROMPT'
};
}
/**
* Returns an action object used to set up any rules that a block editor may
* provide in order to prevent a user from accidentally removing certain
* blocks. These rules are then used to display a confirmation prompt to the
* user. For instance, in the Site Editor, the Query Loop block is important
* enough to warrant such confirmation.
*
* IMPORTANT: Registering rules implicitly signals to the `privateRemoveBlocks`
* action that the editor will be responsible for displaying block removal
* prompts and confirming deletions. This action is meant to be used by
* component `BlockRemovalWarningModal` only.
*
* The data is a record whose keys are block types (e.g. 'core/query') and
* whose values are the explanation to be shown to users (e.g. 'Query Loop
* displays a list of posts or pages.').
*
* Contrast with `displayBlockRemovalPrompt`.
*
* @param {Record<string,string>|false} rules Block removal rules.
* @return {Object} Action object.
*/
function setBlockRemovalRules(rules = false) {
return {
type: 'SET_BLOCK_REMOVAL_RULES',
rules
};
}
/**
* Sets the client ID of the block settings menu that is currently open.
*
* @param {?string} clientId The block client ID.
* @return {Object} Action object.
*/
function setOpenedBlockSettingsMenu(clientId) {
return {
type: 'SET_OPENED_BLOCK_SETTINGS_MENU',
clientId
};
}
function setStyleOverride(id, style) {
return {
type: 'SET_STYLE_OVERRIDE',
id,
style
};
}
function deleteStyleOverride(id) {
return {
type: 'DELETE_STYLE_OVERRIDE',
id
};
}
/**
* Action that sets the element that had focus when focus leaves the editor canvas.
*
* @param {Object} lastFocus The last focused element.
*
*
* @return {Object} Action object.
*/
function setLastFocus(lastFocus = null) {
return {
type: 'LAST_FOCUS',
lastFocus
};
}
/**
* Action that stops temporarily editing as blocks.
*
* @param {string} clientId The block's clientId.
*/
function stopEditingAsBlocks(clientId) {
return ({
select,
dispatch,
registry
}) => {
const focusModeToRevert = unlock(registry.select(store)).getTemporarilyEditingFocusModeToRevert();
dispatch.__unstableMarkNextChangeAsNotPersistent();
dispatch.updateBlockAttributes(clientId, {
templateLock: 'contentOnly'
});
dispatch.updateBlockListSettings(clientId, {
...select.getBlockListSettings(clientId),
templateLock: 'contentOnly'
});
dispatch.updateSettings({
focusMode: focusModeToRevert
});
dispatch.__unstableSetTemporarilyEditingAsBlocks();
};
}
/**
* Returns an action object used in signalling that the user has begun to drag.
*
* @return {Object} Action object.
*/
function startDragging() {
return {
type: 'START_DRAGGING'
};
}
/**
* Returns an action object used in signalling that the user has stopped dragging.
*
* @return {Object} Action object.
*/
function stopDragging() {
return {
type: 'STOP_DRAGGING'
};
}
/**
* @param {string|null} clientId The block's clientId, or `null` to clear.
*
* @return {Object} Action object.
*/
function expandBlock(clientId) {
return {
type: 'SET_BLOCK_EXPANDED_IN_LIST_VIEW',
clientId
};
}
/**
* @param {Object} value
* @param {string} value.rootClientId The root client ID to insert at.
* @param {number} value.index The index to insert at.
*
* @return {Object} Action object.
*/
function setInsertionPoint(value) {
return {
type: 'SET_INSERTION_POINT',
value
};
}
/**
* Temporarily modify/unlock the content-only block for editions.
*
* @param {string} clientId The client id of the block.
*/
const modifyContentLockBlock = clientId => ({
select,
dispatch
}) => {
dispatch.selectBlock(clientId);
dispatch.__unstableMarkNextChangeAsNotPersistent();
dispatch.updateBlockAttributes(clientId, {
templateLock: undefined
});
dispatch.updateBlockListSettings(clientId, {
...select.getBlockListSettings(clientId),
templateLock: false
});
const focusModeToRevert = select.getSettings().focusMode;
dispatch.updateSettings({
focusMode: true
});
dispatch.__unstableSetTemporarilyEditingAsBlocks(clientId, focusModeToRevert);
};
/**
* Sets the zoom level.
*
* @param {number} zoom the new zoom level
* @return {Object} Action object.
*/
const setZoomLevel = (zoom = 100) => ({
select,
dispatch
}) => {
// When switching to zoom-out mode, we need to select the parent section
if (zoom !== 100) {
const firstSelectedClientId = select.getBlockSelectionStart();
const sectionRootClientId = select.getSectionRootClientId();
if (firstSelectedClientId) {
let sectionClientId;
if (sectionRootClientId) {
const sectionClientIds = select.getBlockOrder(sectionRootClientId);
// If the selected block is a section block, use it.
if (sectionClientIds?.includes(firstSelectedClientId)) {
sectionClientId = firstSelectedClientId;
} else {
// If the selected block is not a section block, find
// the parent section that contains the selected block.
sectionClientId = select.getBlockParents(firstSelectedClientId).find(parent => sectionClientIds.includes(parent));
}
} else {
sectionClientId = select.getBlockHierarchyRootClientId(firstSelectedClientId);
}
if (sectionClientId) {
dispatch.selectBlock(sectionClientId);
} else {
dispatch.clearSelectedBlock();
}
(0,external_wp_a11y_namespaceObject.speak)((0,external_wp_i18n_namespaceObject.__)('You are currently in zoom-out mode.'));
}
}
dispatch({
type: 'SET_ZOOM_LEVEL',
zoom
});
};
/**
* Resets the Zoom state.
* @return {Object} Action object.
*/
function resetZoomLevel() {
return {
type: 'RESET_ZOOM_LEVEL'
};
}
;// external ["wp","notices"]
const external_wp_notices_namespaceObject = window["wp"]["notices"];
;// ./node_modules/@wordpress/block-editor/build-module/utils/selection.js
/**
* WordPress dependencies
*/
/**
* A robust way to retain selection position through various
* transforms is to insert a special character at the position and
* then recover it.
*/
const START_OF_SELECTED_AREA = '\u0086';
/**
* Retrieve the block attribute that contains the selection position.
*
* @param {Object} blockAttributes Block attributes.
* @return {string|void} The name of the block attribute that was previously selected.
*/
function retrieveSelectedAttribute(blockAttributes) {
if (!blockAttributes) {
return;
}
return Object.keys(blockAttributes).find(name => {
const value = blockAttributes[name];
return (typeof value === 'string' || value instanceof external_wp_richText_namespaceObject.RichTextData) &&
// To do: refactor this to use rich text's selection instead, so we
// no longer have to use on this hack inserting a special character.
value.toString().indexOf(START_OF_SELECTED_AREA) !== -1;
});
}
function findRichTextAttributeKey(blockType) {
for (const [key, value] of Object.entries(blockType.attributes)) {
if (value.source === 'rich-text' || value.source === 'html') {
return key;
}
}
}
;// ./node_modules/@wordpress/block-editor/build-module/store/actions.js
/* eslint no-console: [ 'error', { allow: [ 'error', 'warn' ] } ] */
/**
* WordPress dependencies
*/
/**
* Internal dependencies
*/
/** @typedef {import('../components/use-on-block-drop/types').WPDropOperation} WPDropOperation */
const actions_castArray = maybeArray => Array.isArray(maybeArray) ? maybeArray : [maybeArray];
/**
* Action that resets blocks state to the specified array of blocks, taking precedence
* over any other content reflected as an edit in state.
*
* @param {Array} blocks Array of blocks.
*/
const resetBlocks = blocks => ({
dispatch
}) => {
dispatch({
type: 'RESET_BLOCKS',
blocks
});
dispatch(validateBlocksToTemplate(blocks));
};
/**
* Block validity is a function of blocks state (at the point of a
* reset) and the template setting. As a compromise to its placement
* across distinct parts of state, it is implemented here as a side
* effect of the block reset action.
*
* @param {Array} blocks Array of blocks.
*/
const validateBlocksToTemplate = blocks => ({
select,
dispatch
}) => {
const template = select.getTemplate();
const templateLock = select.getTemplateLock();
// Unlocked templates are considered always valid because they act
// as default values only.
const isBlocksValidToTemplate = !template || templateLock !== 'all' || (0,external_wp_blocks_namespaceObject.doBlocksMatchTemplate)(blocks, template);
// Update if validity has changed.
const isValidTemplate = select.isValidTemplate();
if (isBlocksValidToTemplate !== isValidTemplate) {
dispatch.setTemplateValidity(isBlocksValidToTemplate);
return isBlocksValidToTemplate;
}
};
/**
* A block selection object.
*
* @typedef {Object} WPBlockSelection
*
* @property {string} clientId A block client ID.
* @property {string} attributeKey A block attribute key.
* @property {number} offset An attribute value offset, based on the rich
* text value. See `wp.richText.create`.
*/
/**
* A selection object.
*
* @typedef {Object} WPSelection
*
* @property {WPBlockSelection} start The selection start.
* @property {WPBlockSelection} end The selection end.
*/
/* eslint-disable jsdoc/valid-types */
/**
* Returns an action object used in signalling that selection state should be
* reset to the specified selection.
*
* @param {WPBlockSelection} selectionStart The selection start.
* @param {WPBlockSelection} selectionEnd The selection end.
* @param {0|-1|null} initialPosition Initial block position.
*
* @return {Object} Action object.
*/
function resetSelection(selectionStart, selectionEnd, initialPosition) {
/* eslint-enable jsdoc/valid-types */
return {
type: 'RESET_SELECTION',
selectionStart,
selectionEnd,
initialPosition
};
}
/**
* Returns an action object used in signalling that blocks have been received.
* Unlike resetBlocks, these should be appended to the existing known set, not
* replacing.
*
* @deprecated
*
* @param {Object[]} blocks Array of block objects.
*
* @return {Object} Action object.
*/
function receiveBlocks(blocks) {
external_wp_deprecated_default()('wp.data.dispatch( "core/block-editor" ).receiveBlocks', {
since: '5.9',
alternative: 'resetBlocks or insertBlocks'
});
return {
type: 'RECEIVE_BLOCKS',
blocks
};
}
/**
* Action that updates attributes of multiple blocks with the specified client IDs.
*
* @param {string|string[]} clientIds Block client IDs.
* @param {Object} attributes Block attributes to be merged. Should be keyed by clientIds if
* uniqueByBlock is true.
* @param {boolean} uniqueByBlock true if each block in clientIds array has a unique set of attributes
* @return {Object} Action object.
*/
function updateBlockAttributes(clientIds, attributes, uniqueByBlock = false) {
return {
type: 'UPDATE_BLOCK_ATTRIBUTES',
clientIds: actions_castArray(clientIds),
attributes,
uniqueByBlock
};
}
/**
* Action that updates the block with the specified client ID.
*
* @param {string} clientId Block client ID.
* @param {Object} updates Block attributes to be merged.
*
* @return {Object} Action object.
*/
function updateBlock(clientId, updates) {
return {
type: 'UPDATE_BLOCK',
clientId,
updates
};
}
/* eslint-disable jsdoc/valid-types */
/**
* Returns an action object used in signalling that the block with the
* specified client ID has been selected, optionally accepting a position
* value reflecting its selection directionality. An initialPosition of -1
* reflects a reverse selection.
*
* @param {string} clientId Block client ID.
* @param {0|-1|null} initialPosition Optional initial position. Pass as -1 to
* reflect reverse selection.
*
* @return {Object} Action object.
*/
function selectBlock(clientId, initialPosition = 0) {
/* eslint-enable jsdoc/valid-types */
return {
type: 'SELECT_BLOCK',
initialPosition,
clientId
};
}
/**
* Returns an action object used in signalling that the block with the
* specified client ID has been hovered.
*
* @param {string} clientId Block client ID.
*
* @return {Object} Action object.
*/
function hoverBlock(clientId) {
return {
type: 'HOVER_BLOCK',
clientId
};
}
/**
* Yields action objects used in signalling that the block preceding the given
* clientId (or optionally, its first parent from bottom to top)
* should be selected.
*
* @param {string} clientId Block client ID.
* @param {boolean} fallbackToParent If true, select the first parent if there is no previous block.
*/
const selectPreviousBlock = (clientId, fallbackToParent = false) => ({
select,
dispatch
}) => {
const previousBlockClientId = select.getPreviousBlockClientId(clientId);
if (previousBlockClientId) {
dispatch.selectBlock(previousBlockClientId, -1);
} else if (fallbackToParent) {
const firstParentClientId = select.getBlockRootClientId(clientId);
if (firstParentClientId) {
dispatch.selectBlock(firstParentClientId, -1);
}
}
};
/**
* Yields action objects used in signalling that the block following the given
* clientId should be selected.
*
* @param {string} clientId Block client ID.
*/
const selectNextBlock = clientId => ({
select,
dispatch
}) => {
const nextBlockClientId = select.getNextBlockClientId(clientId);
if (nextBlockClientId) {
dispatch.selectBlock(nextBlockClientId);
}
};
/**
* Action that starts block multi-selection.
*
* @return {Object} Action object.
*/
function startMultiSelect() {
return {
type: 'START_MULTI_SELECT'
};
}
/**
* Action that stops block multi-selection.
*
* @return {Object} Action object.
*/
function stopMultiSelect() {
return {
type: 'STOP_MULTI_SELECT'
};
}
/**
* Action that changes block multi-selection.
*
* @param {string} start First block of the multi selection.
* @param {string} end Last block of the multiselection.
* @param {number|null} __experimentalInitialPosition Optional initial position. Pass as null to skip focus within editor canvas.
*/
const multiSelect = (start, end, __experimentalInitialPosition = 0) => ({
select,
dispatch
}) => {
const startBlockRootClientId = select.getBlockRootClientId(start);
const endBlockRootClientId = select.getBlockRootClientId(end);
// Only allow block multi-selections at the same level.
if (startBlockRootClientId !== endBlockRootClientId) {
return;
}
dispatch({
type: 'MULTI_SELECT',
start,
end,
initialPosition: __experimentalInitialPosition
});
const blockCount = select.getSelectedBlockCount();
(0,external_wp_a11y_namespaceObject.speak)((0,external_wp_i18n_namespaceObject.sprintf)(/* translators: %s: number of selected blocks */
(0,external_wp_i18n_namespaceObject._n)('%s block selected.', '%s blocks selected.', blockCount), blockCount), 'assertive');
};
/**
* Action that clears the block selection.
*
* @return {Object} Action object.
*/
function clearSelectedBlock() {
return {
type: 'CLEAR_SELECTED_BLOCK'
};
}
/**
* Action that enables or disables block selection.
*
* @param {boolean} [isSelectionEnabled=true] Whether block selection should
* be enabled.
*
* @return {Object} Action object.
*/
function toggleSelection(isSelectionEnabled = true) {
return {
type: 'TOGGLE_SELECTION',
isSelectionEnabled
};
}
/* eslint-disable jsdoc/valid-types */
/**
* Action that replaces given blocks with one or more replacement blocks.
*
* @param {(string|string[])} clientIds Block client ID(s) to replace.
* @param {(Object|Object[])} blocks Replacement block(s).
* @param {number} indexToSelect Index of replacement block to select.
* @param {0|-1|null} initialPosition Index of caret after in the selected block after the operation.
* @param {?Object} meta Optional Meta values to be passed to the action object.
*
* @return {Object} Action object.
*/
const replaceBlocks = (clientIds, blocks, indexToSelect, initialPosition = 0, meta) => ({
select,
dispatch,
registry
}) => {
/* eslint-enable jsdoc/valid-types */
clientIds = actions_castArray(clientIds);
blocks = actions_castArray(blocks);
const rootClientId = select.getBlockRootClientId(clientIds[0]);
// Replace is valid if the new blocks can be inserted in the root block.
for (let index = 0; index < blocks.length; index++) {
const block = blocks[index];
const canInsertBlock = select.canInsertBlockType(block.name, rootClientId);
if (!canInsertBlock) {
return;
}
}
// We're batching these two actions because an extra `undo/redo` step can
// be created, based on whether we insert a default block or not.
registry.batch(() => {
dispatch({
type: 'REPLACE_BLOCKS',
clientIds,
blocks,
time: Date.now(),
indexToSelect,
initialPosition,
meta
});
// To avoid a focus loss when removing the last block, assure there is
// always a default block if the last of the blocks have been removed.
dispatch.ensureDefaultBlock();
});
};
/**
* Action that replaces a single block with one or more replacement blocks.
*
* @param {(string|string[])} clientId Block client ID to replace.
* @param {(Object|Object[])} block Replacement block(s).
*
* @return {Object} Action object.
*/
function replaceBlock(clientId, block) {
return replaceBlocks(clientId, block);
}
/**
* Higher-order action creator which, given the action type to dispatch creates
* an action creator for managing block movement.
*
* @param {string} type Action type to dispatch.
*
* @return {Function} Action creator.
*/
const createOnMove = type => (clientIds, rootClientId) => ({
select,
dispatch
}) => {
// If one of the blocks is locked or the parent is locked, we cannot move any block.
const canMoveBlocks = select.canMoveBlocks(clientIds);
if (!canMoveBlocks) {
return;
}
dispatch({
type,
clientIds: actions_castArray(clientIds),
rootClientId
});
};
const moveBlocksDown = createOnMove('MOVE_BLOCKS_DOWN');
const moveBlocksUp = createOnMove('MOVE_BLOCKS_UP');
/**
* Action that moves given blocks to a new position.
*
* @param {?string} clientIds The client IDs of the blocks.
* @param {?string} fromRootClientId Root client ID source.
* @param {?string} toRootClientId Root client ID destination.
* @param {number} index The index to move the blocks to.
*/
const moveBlocksToPosition = (clientIds, fromRootClientId = '', toRootClientId = '', index) => ({
select,
dispatch
}) => {
const canMoveBlocks = select.canMoveBlocks(clientIds);
// If one of the blocks is locked or the parent is locked, we cannot move any block.
if (!canMoveBlocks) {
return;
}
// If moving inside the same root block the move is always possible.
if (fromRootClientId !== toRootClientId) {
const canRemoveBlocks = select.canRemoveBlocks(clientIds);
// If we're moving to another block, it means we're deleting blocks from
// the original block, so we need to check if removing is possible.
if (!canRemoveBlocks) {
return;
}
const canInsertBlocks = select.canInsertBlocks(clientIds, toRootClientId);
// If moving to other parent block, the move is possible if we can insert a block of the same type inside the new parent block.
if (!canInsertBlocks) {
return;
}
}
dispatch({
type: 'MOVE_BLOCKS_TO_POSITION',
fromRootClientId,
toRootClientId,
clientIds,
index
});
};
/**
* Action that moves given block to a new position.
*
* @param {?string} clientId The client ID of the block.
* @param {?string} fromRootClientId Root client ID source.
* @param {?string} toRootClientId Root client ID destination.
* @param {number} index The index to move the block to.
*/
function moveBlockToPosition(clientId, fromRootClientId = '', toRootClientId = '', index) {
return moveBlocksToPosition([clientId], fromRootClientId, toRootClientId, index);
}
/**
* Action that inserts a single block, optionally at a specific index respective a root block list.
*
* Only allowed blocks are inserted. The action may fail silently for blocks that are not allowed or if
* a templateLock is active on the block list.
*
* @param {Object} block Block object to insert.
* @param {?number} index Index at which block should be inserted.
* @param {?string} rootClientId Optional root client ID of block list on which to insert.
* @param {?boolean} updateSelection If true block selection will be updated. If false, block selection will not change. Defaults to true.
* @param {?Object} meta Optional Meta values to be passed to the action object.
*
* @return {Object} Action object.
*/
function insertBlock(block, index, rootClientId, updateSelection, meta) {
return insertBlocks([block], index, rootClientId, updateSelection, 0, meta);
}
/* eslint-disable jsdoc/valid-types */
/**
* Action that inserts an array of blocks, optionally at a specific index respective a root block list.
*
* Only allowed blocks are inserted. The action may fail silently for blocks that are not allowed or if
* a templateLock is active on the block list.
*
* @param {Object[]} blocks Block objects to insert.
* @param {?number} index Index at which block should be inserted.
* @param {?string} rootClientId Optional root client ID of block list on which to insert.
* @param {?boolean} updateSelection If true block selection will be updated. If false, block selection will not change. Defaults to true.
* @param {0|-1|null} initialPosition Initial focus position. Setting it to null prevent focusing the inserted block.
* @param {?Object} meta Optional Meta values to be passed to the action object.
*
* @return {Object} Action object.
*/
const insertBlocks = (blocks, index, rootClientId, updateSelection = true, initialPosition = 0, meta) => ({
select,
dispatch
}) => {
/* eslint-enable jsdoc/valid-types */
if (initialPosition !== null && typeof initialPosition === 'object') {
meta = initialPosition;
initialPosition = 0;
external_wp_deprecated_default()("meta argument in wp.data.dispatch('core/block-editor')", {
since: '5.8',
hint: 'The meta argument is now the 6th argument of the function'
});
}
blocks = actions_castArray(blocks);
const allowedBlocks = [];
for (const block of blocks) {
const isValid = select.canInsertBlockType(block.name, rootClientId);
if (isValid) {
allowedBlocks.push(block);
}
}
if (allowedBlocks.length) {
dispatch({
type: 'INSERT_BLOCKS',
blocks: allowedBlocks,
index,
rootClientId,
time: Date.now(),
updateSelection,
initialPosition: updateSelection ? initialPosition : null,
meta
});
}
};
/**
* Action that shows the insertion point.
*
* @param {?string} rootClientId Optional root client ID of block list on
* which to insert.
* @param {?number} index Index at which block should be inserted.
* @param {?Object} __unstableOptions Additional options.
* @property {boolean} __unstableWithInserter Whether or not to show an inserter button.
* @property {WPDropOperation} operation The operation to perform when applied,
* either 'insert' or 'replace' for now.
*
* @return {Object} Action object.
*/
function showInsertionPoint(rootClientId, index, __unstableOptions = {}) {
const {
__unstableWithInserter,
operation,
nearestSide
} = __unstableOptions;
return {
type: 'SHOW_INSERTION_POINT',
rootClientId,
index,
__unstableWithInserter,
operation,
nearestSide
};
}
/**
* Action that hides the insertion point.
*/
const hideInsertionPoint = () => ({
select,
dispatch
}) => {
if (!select.isBlockInsertionPointVisible()) {
return;
}
dispatch({
type: 'HIDE_INSERTION_POINT'
});
};
/**
* Action that resets the template validity.
*
* @param {boolean} isValid template validity flag.
*
* @return {Object} Action object.
*/
function setTemplateValidity(isValid) {
return {
type: 'SET_TEMPLATE_VALIDITY',
isValid
};
}
/**
* Action that synchronizes the template with the list of blocks.
*
* @return {Object} Action object.
*/
const synchronizeTemplate = () => ({
select,
dispatch
}) => {
dispatch({
type: 'SYNCHRONIZE_TEMPLATE'
});
const blocks = select.getBlocks();
const template = select.getTemplate();
const updatedBlockList = (0,external_wp_blocks_namespaceObject.synchronizeBlocksWithTemplate)(blocks, template);
dispatch.resetBlocks(updatedBlockList);
};
/**
* Delete the current selection.
*
* @param {boolean} isForward
*/
const __unstableDeleteSelection = isForward => ({
registry,
select,
dispatch
}) => {
const selectionAnchor = select.getSelectionStart();
const selectionFocus = select.getSelectionEnd();
if (selectionAnchor.clientId === selectionFocus.clientId) {
return;
}
// It's not mergeable if there's no rich text selection.
if (!selectionAnchor.attributeKey || !selectionFocus.attributeKey || typeof selectionAnchor.offset === 'undefined' || typeof selectionFocus.offset === 'undefined') {
return false;
}
const anchorRootClientId = select.getBlockRootClientId(selectionAnchor.clientId);
const focusRootClientId = select.getBlockRootClientId(selectionFocus.clientId);
// It's not mergeable if the selection doesn't start and end in the same
// block list. Maybe in the future it should be allowed.
if (anchorRootClientId !== focusRootClientId) {
return;
}
const blockOrder = select.getBlockOrder(anchorRootClientId);
const anchorIndex = blockOrder.indexOf(selectionAnchor.clientId);
const focusIndex = blockOrder.indexOf(selectionFocus.clientId);
// Reassign selection start and end based on order.
let selectionStart, selectionEnd;
if (anchorIndex > focusIndex) {
selectionStart = selectionFocus;
selectionEnd = selectionAnchor;
} else {
selectionStart = selectionAnchor;
selectionEnd = selectionFocus;
}
const targetSelection = isForward ? selectionEnd : selectionStart;
const targetBlock = select.getBlock(targetSelection.clientId);
const targetBlockType = (0,external_wp_blocks_namespaceObject.getBlockType)(targetBlock.name);
if (!targetBlockType.merge) {
return;
}
const selectionA = selectionStart;
const selectionB = selectionEnd;
const blockA = select.getBlock(selectionA.clientId);
const blockB = select.getBlock(selectionB.clientId);
const htmlA = blockA.attributes[selectionA.attributeKey];
const htmlB = blockB.attributes[selectionB.attributeKey];
let valueA = (0,external_wp_richText_namespaceObject.create)({
html: htmlA
});
let valueB = (0,external_wp_richText_namespaceObject.create)({
html: htmlB
});
valueA = (0,external_wp_richText_namespaceObject.remove)(valueA, selectionA.offset, valueA.text.length);
valueB = (0,external_wp_richText_namespaceObject.insert)(valueB, START_OF_SELECTED_AREA, 0, selectionB.offset);
// Clone the blocks so we don't manipulate the original.
const cloneA = (0,external_wp_blocks_namespaceObject.cloneBlock)(blockA, {
[selectionA.attributeKey]: (0,external_wp_richText_namespaceObject.toHTMLString)({
value: valueA
})
});
const cloneB = (0,external_wp_blocks_namespaceObject.cloneBlock)(blockB, {
[selectionB.attributeKey]: (0,external_wp_richText_namespaceObject.toHTMLString)({
value: valueB
})
});
const followingBlock = isForward ? cloneA : cloneB;
// We can only merge blocks with similar types
// thus, we transform the block to merge first
const blocksWithTheSameType = blockA.name === blockB.name ? [followingBlock] : (0,external_wp_blocks_namespaceObject.switchToBlockType)(followingBlock, targetBlockType.name);
// If the block types can not match, do nothing
if (!blocksWithTheSameType || !blocksWithTheSameType.length) {
return;
}
let updatedAttributes;
if (isForward) {
const blockToMerge = blocksWithTheSameType.pop();
updatedAttributes = targetBlockType.merge(blockToMerge.attributes, cloneB.attributes);
} else {
const blockToMerge = blocksWithTheSameType.shift();
updatedAttributes = targetBlockType.merge(cloneA.attributes, blockToMerge.attributes);
}
const newAttributeKey = retrieveSelectedAttribute(updatedAttributes);
const convertedHtml = updatedAttributes[newAttributeKey];
const convertedValue = (0,external_wp_richText_namespaceObject.create)({
html: convertedHtml
});
const newOffset = convertedValue.text.indexOf(START_OF_SELECTED_AREA);
const newValue = (0,external_wp_richText_namespaceObject.remove)(convertedValue, newOffset, newOffset + 1);
const newHtml = (0,external_wp_richText_namespaceObject.toHTMLString)({
value: newValue
});
updatedAttributes[newAttributeKey] = newHtml;
const selectedBlockClientIds = select.getSelectedBlockClientIds();
const replacement = [...(isForward ? blocksWithTheSameType : []), {
// Preserve the original client ID.
...targetBlock,
attributes: {
...targetBlock.attributes,
...updatedAttributes
}
}, ...(isForward ? [] : blocksWithTheSameType)];
registry.batch(() => {
dispatch.selectionChange(targetBlock.clientId, newAttributeKey, newOffset, newOffset);
dispatch.replaceBlocks(selectedBlockClientIds, replacement, 0,
// If we don't pass the `indexToSelect` it will default to the last block.
select.getSelectedBlocksInitialCaretPosition());
});
};
/**
* Split the current selection.
* @param {?Array} blocks
*/
const __unstableSplitSelection = (blocks = []) => ({
registry,
select,
dispatch
}) => {
const selectionAnchor = select.getSelectionStart();
const selectionFocus = select.getSelectionEnd();
const anchorRootClientId = select.getBlockRootClientId(selectionAnchor.clientId);
const focusRootClientId = select.getBlockRootClientId(selectionFocus.clientId);
// It's not splittable if the selection doesn't start and end in the same
// block list. Maybe in the future it should be allowed.
if (anchorRootClientId !== focusRootClientId) {
return;
}
const blockOrder = select.getBlockOrder(anchorRootClientId);
const anchorIndex = blockOrder.indexOf(selectionAnchor.clientId);
const focusIndex = blockOrder.indexOf(selectionFocus.clientId);
// Reassign selection start and end based on order.
let selectionStart, selectionEnd;
if (anchorIndex > focusIndex) {
selectionStart = selectionFocus;
selectionEnd = selectionAnchor;
} else {
selectionStart = selectionAnchor;
selectionEnd = selectionFocus;
}
const selectionA = selectionStart;
const selectionB = selectionEnd;
const blockA = select.getBlock(selectionA.clientId);
const blockB = select.getBlock(selectionB.clientId);
const blockAType = (0,external_wp_blocks_namespaceObject.getBlockType)(blockA.name);
const blockBType = (0,external_wp_blocks_namespaceObject.getBlockType)(blockB.name);
const attributeKeyA = typeof selectionA.attributeKey === 'string' ? selectionA.attributeKey : findRichTextAttributeKey(blockAType);
const attributeKeyB = typeof selectionB.attributeKey === 'string' ? selectionB.attributeKey : findRichTextAttributeKey(blockBType);
const blockAttributes = select.getBlockAttributes(selectionA.clientId);
const bindings = blockAttributes?.metadata?.bindings;
// If the attribute is bound, don't split the selection and insert a new block instead.
if (bindings?.[attributeKeyA]) {
// Show warning if user tries to insert a block into another block with bindings.
if (blocks.length) {
const {
createWarningNotice
} = registry.dispatch(external_wp_notices_namespaceObject.store);
createWarningNotice((0,external_wp_i18n_namespaceObject.__)("Blocks can't be inserted into other blocks with bindings"), {
type: 'snackbar'
});
return;
}
dispatch.insertAfterBlock(selectionA.clientId);
return;
}
// Can't split if the selection is not set.
if (!attributeKeyA || !attributeKeyB || typeof selectionAnchor.offset === 'undefined' || typeof selectionFocus.offset === 'undefined') {
return;
}
// We can do some short-circuiting if the selection is collapsed.
if (selectionA.clientId === selectionB.clientId && attributeKeyA === attributeKeyB && selectionA.offset === selectionB.offset) {
// If an unmodified default block is selected, replace it. We don't
// want to be converting into a default block.
if (blocks.length) {
if ((0,external_wp_blocks_namespaceObject.isUnmodifiedDefaultBlock)(blockA)) {
dispatch.replaceBlocks([selectionA.clientId], blocks, blocks.length - 1, -1);
return;
}
}
// If selection is at the start or end, we can simply insert an
// empty block, provided this block has no inner blocks.
else if (!select.getBlockOrder(selectionA.clientId).length) {
function createEmpty() {
const defaultBlockName = (0,external_wp_blocks_namespaceObject.getDefaultBlockName)();
return select.canInsertBlockType(defaultBlockName, anchorRootClientId) ? (0,external_wp_blocks_namespaceObject.createBlock)(defaultBlockName) : (0,external_wp_blocks_namespaceObject.createBlock)(select.getBlockName(selectionA.clientId));
}
const length = blockAttributes[attributeKeyA].length;
if (selectionA.offset === 0 && length) {
dispatch.insertBlocks([createEmpty()], select.getBlockIndex(selectionA.clientId), anchorRootClientId, false);
return;
}
if (selectionA.offset === length) {
dispatch.insertBlocks([createEmpty()], select.getBlockIndex(selectionA.clientId) + 1, anchorRootClientId);
return;
}
}
}
const htmlA = blockA.attributes[attributeKeyA];
const htmlB = blockB.attributes[attributeKeyB];
let valueA = (0,external_wp_richText_namespaceObject.create)({
html: htmlA
});
let valueB = (0,external_wp_richText_namespaceObject.create)({
html: htmlB
});
valueA = (0,external_wp_richText_namespaceObject.remove)(valueA, selectionA.offset, valueA.text.length);
valueB = (0,external_wp_richText_namespaceObject.remove)(valueB, 0, selectionB.offset);
let head = {
// Preserve the original client ID.
...blockA,
// If both start and end are the same, should only copy innerBlocks
// once.
innerBlocks: blockA.clientId === blockB.clientId ? [] : blockA.innerBlocks,
attributes: {
...blockA.attributes,
[attributeKeyA]: (0,external_wp_richText_namespaceObject.toHTMLString)({
value: valueA
})
}
};
let tail = {
...blockB,
// Only preserve the original client ID if the end is different.
clientId: blockA.clientId === blockB.clientId ? (0,external_wp_blocks_namespaceObject.createBlock)(blockB.name).clientId : blockB.clientId,
attributes: {
...blockB.attributes,
[attributeKeyB]: (0,external_wp_richText_namespaceObject.toHTMLString)({
value: valueB
})
}
};
// When splitting a block, attempt to convert the tail block to the
// default block type. For example, when splitting a heading block, the
// tail block will be converted to a paragraph block. Note that for
// blocks such as a list item and button, this will be skipped because
// the default block type cannot be inserted.
const defaultBlockName = (0,external_wp_blocks_namespaceObject.getDefaultBlockName)();
if (
// A block is only split when the selection is within the same
// block.
blockA.clientId === blockB.clientId && defaultBlockName && tail.name !== defaultBlockName && select.canInsertBlockType(defaultBlockName, anchorRootClientId)) {
const switched = (0,external_wp_blocks_namespaceObject.switchToBlockType)(tail, defaultBlockName);
if (switched?.length === 1) {
tail = switched[0];
}
}
if (!blocks.length) {
dispatch.replaceBlocks(select.getSelectedBlockClientIds(), [head, tail]);
return;
}
let selection;
const output = [];
const clonedBlocks = [...blocks];
const firstBlock = clonedBlocks.shift();
const headType = (0,external_wp_blocks_namespaceObject.getBlockType)(head.name);
const firstBlocks = headType.merge && firstBlock.name === headType.name ? [firstBlock] : (0,external_wp_blocks_namespaceObject.switchToBlockType)(firstBlock, headType.name);
if (firstBlocks?.length) {
const first = firstBlocks.shift();
head = {
...head,
attributes: {
...head.attributes,
...headType.merge(head.attributes, first.attributes)
}
};
output.push(head);
selection = {
clientId: head.clientId,
attributeKey: attributeKeyA,
offset: (0,external_wp_richText_namespaceObject.create)({
html: head.attributes[attributeKeyA]
}).text.length
};
clonedBlocks.unshift(...firstBlocks);
} else {
if (!(0,external_wp_blocks_namespaceObject.isUnmodifiedBlock)(head)) {
output.push(head);
}
output.push(firstBlock);
}
const lastBlock = clonedBlocks.pop();
const tailType = (0,external_wp_blocks_namespaceObject.getBlockType)(tail.name);
if (clonedBlocks.length) {
output.push(...clonedBlocks);
}
if (lastBlock) {
const lastBlocks = tailType.merge && tailType.name === lastBlock.name ? [lastBlock] : (0,external_wp_blocks_namespaceObject.switchToBlockType)(lastBlock, tailType.name);
if (lastBlocks?.length) {
const last = lastBlocks.pop();
output.push({
...tail,
attributes: {
...tail.attributes,
...tailType.merge(last.attributes, tail.attributes)
}
});
output.push(...lastBlocks);
selection = {
clientId: tail.clientId,
attributeKey: attributeKeyB,
offset: (0,external_wp_richText_namespaceObject.create)({
html: last.attributes[attributeKeyB]
}).text.length
};
} else {
output.push(lastBlock);
if (!(0,external_wp_blocks_namespaceObject.isUnmodifiedBlock)(tail)) {
output.push(tail);
}
}
} else if (!(0,external_wp_blocks_namespaceObject.isUnmodifiedBlock)(tail)) {
output.push(tail);
}
registry.batch(() => {
dispatch.replaceBlocks(select.getSelectedBlockClientIds(), output, output.length - 1, 0);
if (selection) {
dispatch.selectionChange(selection.clientId, selection.attributeKey, selection.offset, selection.offset);
}
});
};
/**
* Expand the selection to cover the entire blocks, removing partial selection.
*/
const __unstableExpandSelection = () => ({
select,
dispatch
}) => {
const selectionAnchor = select.getSelectionStart();
const selectionFocus = select.getSelectionEnd();
dispatch.selectionChange({
start: {
clientId: selectionAnchor.clientId
},
end: {
clientId: selectionFocus.clientId
}
});
};
/**
* Action that merges two blocks.
*
* @param {string} firstBlockClientId Client ID of the first block to merge.
* @param {string} secondBlockClientId Client ID of the second block to merge.
*/
const mergeBlocks = (firstBlockClientId, secondBlockClientId) => ({
registry,
select,
dispatch
}) => {
const clientIdA = firstBlockClientId;
const clientIdB = secondBlockClientId;
const blockA = select.getBlock(clientIdA);
const blockAType = (0,external_wp_blocks_namespaceObject.getBlockType)(blockA.name);
if (!blockAType) {
return;
}
const blockB = select.getBlock(clientIdB);
if (!blockAType.merge && (0,external_wp_blocks_namespaceObject.getBlockSupport)(blockA.name, '__experimentalOnMerge')) {
// If there's no merge function defined, attempt merging inner
// blocks.
const blocksWithTheSameType = (0,external_wp_blocks_namespaceObject.switchToBlockType)(blockB, blockAType.name);
// Only focus the previous block if it's not mergeable.
if (blocksWithTheSameType?.length !== 1) {
dispatch.selectBlock(blockA.clientId);
return;
}
const [blockWithSameType] = blocksWithTheSameType;
if (blockWithSameType.innerBlocks.length < 1) {
dispatch.selectBlock(blockA.clientId);
return;
}
registry.batch(() => {
dispatch.insertBlocks(blockWithSameType.innerBlocks, undefined, clientIdA);
dispatch.removeBlock(clientIdB);
dispatch.selectBlock(blockWithSameType.innerBlocks[0].clientId);
// Attempt to merge the next block if it's the same type and
// same attributes. This is useful when merging a paragraph into
// a list, and the next block is also a list. If we don't merge,
// it looks like one list, but it's actually two lists. The same
// applies to other blocks such as a group with the same
// attributes.
const nextBlockClientId = select.getNextBlockClientId(clientIdA);
if (nextBlockClientId && select.getBlockName(clientIdA) === select.getBlockName(nextBlockClientId)) {
const rootAttributes = select.getBlockAttributes(clientIdA);
const previousRootAttributes = select.getBlockAttributes(nextBlockClientId);
if (Object.keys(rootAttributes).every(key => rootAttributes[key] === previousRootAttributes[key])) {
dispatch.moveBlocksToPosition(select.getBlockOrder(nextBlockClientId), nextBlockClientId, clientIdA);
dispatch.removeBlock(nextBlockClientId, false);
}
}
});
return;
}
if ((0,external_wp_blocks_namespaceObject.isUnmodifiedDefaultBlock)(blockA)) {
dispatch.removeBlock(clientIdA, select.isBlockSelected(clientIdA));
return;
}
if ((0,external_wp_blocks_namespaceObject.isUnmodifiedDefaultBlock)(blockB)) {
dispatch.removeBlock(clientIdB, select.isBlockSelected(clientIdB));
return;
}
if (!blockAType.merge) {
dispatch.selectBlock(blockA.clientId);
return;
}
const blockBType = (0,external_wp_blocks_namespaceObject.getBlockType)(blockB.name);
const {
clientId,
attributeKey,
offset
} = select.getSelectionStart();
const selectedBlockType = clientId === clientIdA ? blockAType : blockBType;
const attributeDefinition = selectedBlockType.attributes[attributeKey];
const canRestoreTextSelection = (clientId === clientIdA || clientId === clientIdB) && attributeKey !== undefined && offset !== undefined &&
// We cannot restore text selection if the RichText identifier
// is not a defined block attribute key. This can be the case if the
// fallback instance ID is used to store selection (and no RichText
// identifier is set), or when the identifier is wrong.
!!attributeDefinition;
if (!attributeDefinition) {
if (typeof attributeKey === 'number') {
window.console.error(`RichText needs an identifier prop that is the block attribute key of the attribute it controls. Its type is expected to be a string, but was ${typeof attributeKey}`);
} else {
window.console.error('The RichText identifier prop does not match any attributes defined by the block.');
}
}
// Clone the blocks so we don't insert the character in a "live" block.
const cloneA = (0,external_wp_blocks_namespaceObject.cloneBlock)(blockA);
const cloneB = (0,external_wp_blocks_namespaceObject.cloneBlock)(blockB);
if (canRestoreTextSelection) {
const selectedBlock = clientId === clientIdA ? cloneA : cloneB;
const html = selectedBlock.attributes[attributeKey];
const value = (0,external_wp_richText_namespaceObject.insert)((0,external_wp_richText_namespaceObject.create)({
html
}), START_OF_SELECTED_AREA, offset, offset);
selectedBlock.attributes[attributeKey] = (0,external_wp_richText_namespaceObject.toHTMLString)({
value
});
}
// We can only merge blocks with similar types
// thus, we transform the block to merge first.
const blocksWithTheSameType = blockA.name === blockB.name ? [cloneB] : (0,external_wp_blocks_namespaceObject.switchToBlockType)(cloneB, blockA.name);
// If the block types can not match, do nothing.
if (!blocksWithTheSameType || !blocksWithTheSameType.length) {
return;
}
// Calling the merge to update the attributes and remove the block to be merged.
const updatedAttributes = blockAType.merge(cloneA.attributes, blocksWithTheSameType[0].attributes);
if (canRestoreTextSelection) {
const newAttributeKey = retrieveSelectedAttribute(updatedAttributes);
const convertedHtml = updatedAttributes[newAttributeKey];
const convertedValue = (0,external_wp_richText_namespaceObject.create)({
html: convertedHtml
});
const newOffset = convertedValue.text.indexOf(START_OF_SELECTED_AREA);
const newValue = (0,external_wp_richText_namespaceObject.remove)(convertedValue, newOffset, newOffset + 1);
const newHtml = (0,external_wp_richText_namespaceObject.toHTMLString)({
value: newValue
});
updatedAttributes[newAttributeKey] = newHtml;
dispatch.selectionChange(blockA.clientId, newAttributeKey, newOffset, newOffset);
}
dispatch.replaceBlocks([blockA.clientId, blockB.clientId], [{
...blockA,
attributes: {
...blockA.attributes,
...updatedAttributes
}
}, ...blocksWithTheSameType.slice(1)], 0 // If we don't pass the `indexToSelect` it will default to the last block.
);
};
/**
* Yields action objects used in signalling that the blocks corresponding to
* the set of specified client IDs are to be removed.
*
* @param {string|string[]} clientIds Client IDs of blocks to remove.
* @param {boolean} selectPrevious True if the previous block
* or the immediate parent
* (if no previous block exists)
* should be selected
* when a block is removed.
*/
const removeBlocks = (clientIds, selectPrevious = true) => privateRemoveBlocks(clientIds, selectPrevious);
/**
* Returns an action object used in signalling that the block with the
* specified client ID is to be removed.
*
* @param {string} clientId Client ID of block to remove.
* @param {boolean} selectPrevious True if the previous block should be
* selected when a block is removed.
*
* @return {Object} Action object.
*/
function removeBlock(clientId, selectPrevious) {
return removeBlocks([clientId], selectPrevious);
}
/* eslint-disable jsdoc/valid-types */
/**
* Returns an action object used in signalling that the inner blocks with the
* specified client ID should be replaced.
*
* @param {string} rootClientId Client ID of the block whose InnerBlocks will re replaced.
* @param {Object[]} blocks Block objects to insert as new InnerBlocks
* @param {?boolean} updateSelection If true block selection will be updated. If false, block selection will not change. Defaults to false.
* @param {0|-1|null} initialPosition Initial block position.
* @return {Object} Action object.
*/
function replaceInnerBlocks(rootClientId, blocks, updateSelection = false, initialPosition = 0) {
/* eslint-enable jsdoc/valid-types */
return {
type: 'REPLACE_INNER_BLOCKS',
rootClientId,
blocks,
updateSelection,
initialPosition: updateSelection ? initialPosition : null,
time: Date.now()
};
}
/**
* Returns an action object used to toggle the block editing mode between
* visual and HTML modes.
*
* @param {string} clientId Block client ID.
*
* @return {Object} Action object.
*/
function toggleBlockMode(clientId) {
return {
type: 'TOGGLE_BLOCK_MODE',
clientId
};
}
/**
* Returns an action object used in signalling that the user has begun to type.
*
* @return {Object} Action object.
*/
function startTyping() {
return {
type: 'START_TYPING'
};
}
/**
* Returns an action object used in signalling that the user has stopped typing.
*
* @return {Object} Action object.
*/
function stopTyping() {
return {
type: 'STOP_TYPING'
};
}
/**
* Returns an action object used in signalling that the user has begun to drag blocks.
*
* @param {string[]} clientIds An array of client ids being dragged
*
* @return {Object} Action object.
*/
function startDraggingBlocks(clientIds = []) {
return {
type: 'START_DRAGGING_BLOCKS',
clientIds
};
}
/**
* Returns an action object used in signalling that the user has stopped dragging blocks.
*
* @return {Object} Action object.
*/
function stopDraggingBlocks() {
return {
type: 'STOP_DRAGGING_BLOCKS'
};
}
/**
* Returns an action object used in signalling that the caret has entered formatted text.
*
* @deprecated
*
* @return {Object} Action object.
*/
function enterFormattedText() {
external_wp_deprecated_default()('wp.data.dispatch( "core/block-editor" ).enterFormattedText', {
since: '6.1',
version: '6.3'
});
return {
type: 'DO_NOTHING'
};
}
/**
* Returns an action object used in signalling that the user caret has exited formatted text.
*
* @deprecated
*
* @return {Object} Action object.
*/
function exitFormattedText() {
external_wp_deprecated_default()('wp.data.dispatch( "core/block-editor" ).exitFormattedText', {
since: '6.1',
version: '6.3'
});
return {
type: 'DO_NOTHING'
};
}
/**
* Action that changes the position of the user caret.
*
* @param {string|WPSelection} clientId The selected block client ID.
* @param {string} attributeKey The selected block attribute key.
* @param {number} startOffset The start offset.
* @param {number} endOffset The end offset.
*
* @return {Object} Action object.
*/
function selectionChange(clientId, attributeKey, startOffset, endOffset) {
if (typeof clientId === 'string') {
return {
type: 'SELECTION_CHANGE',
clientId,
attributeKey,
startOffset,
endOffset
};
}
return {
type: 'SELECTION_CHANGE',
...clientId
};
}
/**
* Action that adds a new block of the default type to the block list.
*
* @param {?Object} attributes Optional attributes of the block to assign.
* @param {?string} rootClientId Optional root client ID of block list on which
* to append.
* @param {?number} index Optional index where to insert the default block.
*/
const insertDefaultBlock = (attributes, rootClientId, index) => ({
dispatch
}) => {
// Abort if there is no default block type (if it has been unregistered).
const defaultBlockName = (0,external_wp_blocks_namespaceObject.getDefaultBlockName)();
if (!defaultBlockName) {
return;
}
const block = (0,external_wp_blocks_namespaceObject.createBlock)(defaultBlockName, attributes);
return dispatch.insertBlock(block, index, rootClientId);
};
/**
* @typedef {Object< string, Object >} SettingsByClientId
*/
/**
* Action that changes the nested settings of the given block(s).
*
* @param {string | SettingsByClientId} clientId Client ID of the block whose
* nested setting are being
* received, or object of settings
* by client ID.
* @param {Object} settings Object with the new settings
* for the nested block.
*
* @return {Object} Action object
*/
function updateBlockListSettings(clientId, settings) {
return {
type: 'UPDATE_BLOCK_LIST_SETTINGS',
clientId,
settings
};
}
/**
* Action that updates the block editor settings.
*
* @param {Object} settings Updated settings
*
* @return {Object} Action object
*/
function updateSettings(settings) {
return __experimentalUpdateSettings(settings, {
stripExperimentalSettings: true
});
}
/**
* Action that signals that a temporary reusable block has been saved
* in order to switch its temporary id with the real id.
*
* @param {string} id Reusable block's id.
* @param {string} updatedId Updated block's id.
*
* @return {Object} Action object.
*/
function __unstableSaveReusableBlock(id, updatedId) {
return {
type: 'SAVE_REUSABLE_BLOCK_SUCCESS',
id,
updatedId
};
}
/**
* Action that marks the last block change explicitly as persistent.
*
* @return {Object} Action object.
*/
function __unstableMarkLastChangeAsPersistent() {
return {
type: 'MARK_LAST_CHANGE_AS_PERSISTENT'
};
}
/**
* Action that signals that the next block change should be marked explicitly as not persistent.
*
* @return {Object} Action object.
*/
function __unstableMarkNextChangeAsNotPersistent() {
return {
type: 'MARK_NEXT_CHANGE_AS_NOT_PERSISTENT'
};
}
/**
* Action that marks the last block change as an automatic change, meaning it was not
* performed by the user, and can be undone using the `Escape` and `Backspace` keys.
* This action must be called after the change was made, and any actions that are a
* consequence of it, so it is recommended to be called at the next idle period to ensure all
* selection changes have been recorded.
*/
const __unstableMarkAutomaticChange = () => ({
dispatch
}) => {
dispatch({
type: 'MARK_AUTOMATIC_CHANGE'
});
const {
requestIdleCallback = cb => setTimeout(cb, 100)
} = window;
requestIdleCallback(() => {
dispatch({
type: 'MARK_AUTOMATIC_CHANGE_FINAL'
});
});
};
/**
* Action that enables or disables the navigation mode.
*
* @param {boolean} isNavigationMode Enable/Disable navigation mode.
*/
const setNavigationMode = (isNavigationMode = true) => ({
dispatch
}) => {
dispatch.__unstableSetEditorMode(isNavigationMode ? 'navigation' : 'edit');
};
/**
* Action that sets the editor mode
*
* @param {string} mode Editor mode
*/
const __unstableSetEditorMode = mode => ({
registry
}) => {
registry.dispatch(external_wp_preferences_namespaceObject.store).set('core', 'editorTool', mode);
if (mode === 'navigation') {
(0,external_wp_a11y_namespaceObject.speak)((0,external_wp_i18n_namespaceObject.__)('You are currently in Write mode.'));
} else if (mode === 'edit') {
(0,external_wp_a11y_namespaceObject.speak)((0,external_wp_i18n_namespaceObject.__)('You are currently in Design mode.'));
}
};
/**
* Set the block moving client ID.
*
* @deprecated
*
* @return {Object} Action object.
*/
function setBlockMovingClientId() {
external_wp_deprecated_default()('wp.data.dispatch( "core/block-editor" ).setBlockMovingClientId', {
since: '6.7',
hint: 'Block moving mode feature has been removed'
});
return {
type: 'DO_NOTHING'
};
}
/**
* Action that duplicates a list of blocks.
*
* @param {string[]} clientIds
* @param {boolean} updateSelection
*/
const duplicateBlocks = (clientIds, updateSelection = true) => ({
select,
dispatch
}) => {
if (!clientIds || !clientIds.length) {
return;
}
// Return early if blocks don't exist.
const blocks = select.getBlocksByClientId(clientIds);
if (blocks.some(block => !block)) {
return;
}
// Return early if blocks don't support multiple usage.
const blockNames = blocks.map(block => block.name);
if (blockNames.some(blockName => !(0,external_wp_blocks_namespaceObject.hasBlockSupport)(blockName, 'multiple', true))) {
return;
}
const rootClientId = select.getBlockRootClientId(clientIds[0]);
const clientIdsArray = actions_castArray(clientIds);
const lastSelectedIndex = select.getBlockIndex(clientIdsArray[clientIdsArray.length - 1]);
const clonedBlocks = blocks.map(block => (0,external_wp_blocks_namespaceObject.__experimentalCloneSanitizedBlock)(block));
dispatch.insertBlocks(clonedBlocks, lastSelectedIndex + 1, rootClientId, updateSelection);
if (clonedBlocks.length > 1 && updateSelection) {
dispatch.multiSelect(clonedBlocks[0].clientId, clonedBlocks[clonedBlocks.length - 1].clientId);
}
return clonedBlocks.map(block => block.clientId);
};
/**
* Action that inserts a default block before a given block.
*
* @param {string} clientId
*/
const insertBeforeBlock = clientId => ({
select,
dispatch
}) => {
if (!clientId) {
return;
}
const rootClientId = select.getBlockRootClientId(clientId);
const isLocked = select.getTemplateLock(rootClientId);
if (isLocked) {
return;
}
const blockIndex = select.getBlockIndex(clientId);
const directInsertBlock = rootClientId ? select.getDirectInsertBlock(rootClientId) : null;
if (!directInsertBlock) {
return dispatch.insertDefaultBlock({}, rootClientId, blockIndex);
}
const copiedAttributes = {};
if (directInsertBlock.attributesToCopy) {
const attributes = select.getBlockAttributes(clientId);
directInsertBlock.attributesToCopy.forEach(key => {
if (attributes[key]) {
copiedAttributes[key] = attributes[key];
}
});
}
const block = (0,external_wp_blocks_namespaceObject.createBlock)(directInsertBlock.name, {
...directInsertBlock.attributes,
...copiedAttributes
});
return dispatch.insertBlock(block, blockIndex, rootClientId);
};
/**
* Action that inserts a default block after a given block.
*
* @param {string} clientId
*/
const insertAfterBlock = clientId => ({
select,
dispatch
}) => {
if (!clientId) {
return;
}
const rootClientId = select.getBlockRootClientId(clientId);
const isLocked = select.getTemplateLock(rootClientId);
if (isLocked) {
return;
}
const blockIndex = select.getBlockIndex(clientId);
const directInsertBlock = rootClientId ? select.getDirectInsertBlock(rootClientId) : null;
if (!directInsertBlock) {
return dispatch.insertDefaultBlock({}, rootClientId, blockIndex + 1);
}
const copiedAttributes = {};
if (directInsertBlock.attributesToCopy) {
const attributes = select.getBlockAttributes(clientId);
directInsertBlock.attributesToCopy.forEach(key => {
if (attributes[key]) {
copiedAttributes[key] = attributes[key];
}
});
}
const block = (0,external_wp_blocks_namespaceObject.createBlock)(directInsertBlock.name, {
...directInsertBlock.attributes,
...copiedAttributes
});
return dispatch.insertBlock(block, blockIndex + 1, rootClientId);
};
/**
* Action that toggles the highlighted block state.
*
* @param {string} clientId The block's clientId.
* @param {boolean} isHighlighted The highlight state.
*/
function toggleBlockHighlight(clientId, isHighlighted) {
return {
type: 'TOGGLE_BLOCK_HIGHLIGHT',
clientId,
isHighlighted
};
}
/**
* Action that "flashes" the block with a given `clientId` by rhythmically highlighting it.
*
* @param {string} clientId Target block client ID.
*/
const flashBlock = clientId => async ({
dispatch
}) => {
dispatch(toggleBlockHighlight(clientId, true));
await new Promise(resolve => setTimeout(resolve, 150));
dispatch(toggleBlockHighlight(clientId, false));
};
/**
* Action that sets whether a block has controlled inner blocks.
*
* @param {string} clientId The block's clientId.
* @param {boolean} hasControlledInnerBlocks True if the block's inner blocks are controlled.
*/
function setHasControlledInnerBlocks(clientId, hasControlledInnerBlocks) {
return {
type: 'SET_HAS_CONTROLLED_INNER_BLOCKS',
hasControlledInnerBlocks,
clientId
};
}
/**
* Action that sets whether given blocks are visible on the canvas.
*
* @param {Record<string,boolean>} updates For each block's clientId, its new visibility setting.
*/
function setBlockVisibility(updates) {
return {
type: 'SET_BLOCK_VISIBILITY',
updates
};
}
/**
* Action that sets whether a block is being temporarily edited as blocks.
*
* DO-NOT-USE in production.
* This action is created for internal/experimental only usage and may be
* removed anytime without any warning, causing breakage on any plugin or theme invoking it.
*
* @param {?string} temporarilyEditingAsBlocks The block's clientId being temporarily edited as blocks.
* @param {?string} focusModeToRevert The focus mode to revert after temporarily edit as blocks finishes.
*/
function __unstableSetTemporarilyEditingAsBlocks(temporarilyEditingAsBlocks, focusModeToRevert) {
return {
type: 'SET_TEMPORARILY_EDITING_AS_BLOCKS',
temporarilyEditingAsBlocks,
focusModeToRevert
};
}
/**
* Interface for inserter media requests.
*
* @typedef {Object} InserterMediaRequest
* @property {number} per_page How many items to fetch per page.
* @property {string} search The search term to use for filtering the results.
*/
/**
* Interface for inserter media responses. Any media resource should
* map their response to this interface, in order to create the core
* WordPress media blocks (image, video, audio).
*
* @typedef {Object} InserterMediaItem
* @property {string} title The title of the media item.
* @property {string} url The source url of the media item.
* @property {string} [previewUrl] The preview source url of the media item to display in the media list.
* @property {number} [id] The WordPress id of the media item.
* @property {number|string} [sourceId] The id of the media item from external source.
* @property {string} [alt] The alt text of the media item.
* @property {string} [caption] The caption of the media item.
*/
/**
* Registers a new inserter media category. Once registered, the media category is
* available in the inserter's media tab.
*
* The following interfaces are used:
*
* _Type Definition_
*
* - _InserterMediaRequest_ `Object`: Interface for inserter media requests.
*
* _Properties_
*
* - _per_page_ `number`: How many items to fetch per page.
* - _search_ `string`: The search term to use for filtering the results.
*
* _Type Definition_
*
* - _InserterMediaItem_ `Object`: Interface for inserter media responses. Any media resource should
* map their response to this interface, in order to create the core
* WordPress media blocks (image, video, audio).
*
* _Properties_
*
* - _title_ `string`: The title of the media item.
* - _url_ `string: The source url of the media item.
* - _previewUrl_ `[string]`: The preview source url of the media item to display in the media list.
* - _id_ `[number]`: The WordPress id of the media item.
* - _sourceId_ `[number|string]`: The id of the media item from external source.
* - _alt_ `[string]`: The alt text of the media item.
* - _caption_ `[string]`: The caption of the media item.
*
* @param {InserterMediaCategory} category The inserter media category to register.
*
* @example
* ```js
*
* wp.data.dispatch('core/block-editor').registerInserterMediaCategory( {
* name: 'openverse',
* labels: {
* name: 'Openverse',
* search_items: 'Search Openverse',
* },
* mediaType: 'image',
* async fetch( query = {} ) {
* const defaultArgs = {
* mature: false,
* excluded_source: 'flickr,inaturalist,wikimedia',
* license: 'pdm,cc0',
* };
* const finalQuery = { ...query, ...defaultArgs };
* // Sometimes you might need to map the supported request params according to `InserterMediaRequest`.
* // interface. In this example the `search` query param is named `q`.
* const mapFromInserterMediaRequest = {
* per_page: 'page_size',
* search: 'q',
* };
* const url = new URL( 'https://api.openverse.org/v1/images/' );
* Object.entries( finalQuery ).forEach( ( [ key, value ] ) => {
* const queryKey = mapFromInserterMediaRequest[ key ] || key;
* url.searchParams.set( queryKey, value );
* } );
* const response = await window.fetch( url, {
* headers: {
* 'User-Agent': 'WordPress/inserter-media-fetch',
* },
* } );
* const jsonResponse = await response.json();
* const results = jsonResponse.results;
* return results.map( ( result ) => ( {
* ...result,
* // If your response result includes an `id` prop that you want to access later, it should
* // be mapped to `InserterMediaItem`'s `sourceId` prop. This can be useful if you provide
* // a report URL getter.
* // Additionally you should always clear the `id` value of your response results because
* // it is used to identify WordPress media items.
* sourceId: result.id,
* id: undefined,
* caption: result.caption,
* previewUrl: result.thumbnail,
* } ) );
* },
* getReportUrl: ( { sourceId } ) =>
* `https://wordpress.org/openverse/image/${ sourceId }/report/`,
* isExternalResource: true,
* } );
* ```
*
* @typedef {Object} InserterMediaCategory Interface for inserter media category.
* @property {string} name The name of the media category, that should be unique among all media categories.
* @property {Object} labels Labels for the media category.
* @property {string} labels.name General name of the media category. It's used in the inserter media items list.
* @property {string} [labels.search_items='Search'] Label for searching items. Default is ‘Search Posts’ / ‘Search Pages’.
* @property {('image'|'audio'|'video')} mediaType The media type of the media category.
* @property {(InserterMediaRequest) => Promise<InserterMediaItem[]>} fetch The function to fetch media items for the category.
* @property {(InserterMediaItem) => string} [getReportUrl] If the media category supports reporting media items, this function should return
* the report url for the media item. It accepts the `InserterMediaItem` as an argument.
* @property {boolean} [isExternalResource] If the media category is an external resource, this should be set to true.
* This is used to avoid making a request to the external resource when the user
*/
const registerInserterMediaCategory = category => ({
select,
dispatch
}) => {
if (!category || typeof category !== 'object') {
console.error('Category should be an `InserterMediaCategory` object.');
return;
}
if (!category.name) {
console.error('Category should have a `name` that should be unique among all media categories.');
return;
}
if (!category.labels?.name) {
console.error('Category should have a `labels.name`.');
return;
}
if (!['image', 'audio', 'video'].includes(category.mediaType)) {
console.error('Category should have `mediaType` property that is one of `image|audio|video`.');
return;
}
if (!category.fetch || typeof category.fetch !== 'function') {
console.error('Category should have a `fetch` function defined with the following signature `(InserterMediaRequest) => Promise<InserterMediaItem[]>`.');
return;
}
const registeredInserterMediaCategories = select.getRegisteredInserterMediaCategories();
if (registeredInserterMediaCategories.some(({
name
}) => name === category.name)) {
console.error(`A category is already registered with the same name: "${category.name}".`);
return;
}
if (registeredInserterMediaCategories.some(({
labels: {
name
} = {}
}) => name === category.labels?.name)) {
console.error(`A category is already registered with the same labels.name: "${category.labels.name}".`);
return;
}
// `inserterMediaCategories` is a private block editor setting, which means it cannot
// be updated through the public `updateSettings` action. We preserve this setting as
// private, so extenders can only add new inserter media categories and don't have any
// control over the core media categories.
dispatch({
type: 'REGISTER_INSERTER_MEDIA_CATEGORY',
category: {
...category,
isExternalResource: true
}
});
};
/**
* @typedef {import('../components/block-editing-mode').BlockEditingMode} BlockEditingMode
*/
/**
* Sets the block editing mode for a given block.
*
* @see useBlockEditingMode
*
* @param {string} clientId The block client ID, or `''` for the root container.
* @param {BlockEditingMode} mode The block editing mode. One of `'disabled'`,
* `'contentOnly'`, or `'default'`.
*
* @return {Object} Action object.
*/
function setBlockEditingMode(clientId = '', mode) {
return {
type: 'SET_BLOCK_EDITING_MODE',
clientId,
mode
};
}
/**
* Clears the block editing mode for a given block.
*
* @see useBlockEditingMode
*
* @param {string} clientId The block client ID, or `''` for the root container.
*
* @return {Object} Action object.
*/
function unsetBlockEditingMode(clientId = '') {
return {
type: 'UNSET_BLOCK_EDITING_MODE',
clientId
};
}
;// ./node_modules/@wordpress/block-editor/build-module/store/index.js
/**
* WordPress dependencies
*/
/**
* Internal dependencies
*/
/**
* Block editor data store configuration.
*
* @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#registerStore
*/
const storeConfig = {
reducer: reducer,
selectors: selectors_namespaceObject,
actions: actions_namespaceObject
};
/**
* Store definition for the block editor namespace.
*
* @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#createReduxStore
*/
const store = (0,external_wp_data_namespaceObject.createReduxStore)(STORE_NAME, {
...storeConfig,
persist: ['preferences']
});
// We will be able to use the `register` function once we switch
// the "preferences" persistence to use the new preferences package.
const registeredStore = (0,external_wp_data_namespaceObject.registerStore)(STORE_NAME, {
...storeConfig,
persist: ['preferences']
});
unlock(registeredStore).registerPrivateActions(private_actions_namespaceObject);
unlock(registeredStore).registerPrivateSelectors(private_selectors_namespaceObject);
// TODO: Remove once we switch to the `register` function (see above).
//
// Until then, private functions also need to be attached to the original
// `store` descriptor in order to avoid unit tests failing, which could happen
// when tests create new registries in which they register stores.
//
// @see https://github.com/WordPress/gutenberg/pull/51145#discussion_r1239999590
unlock(store).registerPrivateActions(private_actions_namespaceObject);
unlock(store).registerPrivateSelectors(private_selectors_namespaceObject);
;// ./node_modules/@wordpress/block-editor/build-module/components/use-settings/index.js
/**
* WordPress dependencies
*/
/**
* Internal dependencies
*/
/**
* Hook that retrieves the given settings for the block instance in use.
*
* It looks up the settings first in the block instance hierarchy.
* If none are found, it'll look them up in the block editor settings.
*
* @param {string[]} paths The paths to the settings.
* @return {any[]} Returns the values defined for the settings.
* @example
* ```js
* const [ fixed, sticky ] = useSettings( 'position.fixed', 'position.sticky' );
* ```
*/
function use_settings_useSettings(...paths) {
const {
clientId = null
} = useBlockEditContext();
return (0,external_wp_data_namespaceObject.useSelect)(select => unlock(select(store)).getBlockSettings(clientId, ...paths), [clientId, ...paths]);
}
/**
* Hook that retrieves the given setting for the block instance in use.
*
* It looks up the setting first in the block instance hierarchy.
* If none is found, it'll look it up in the block editor settings.
*
* @deprecated 6.5.0 Use useSettings instead.
*
* @param {string} path The path to the setting.
* @return {any} Returns the value defined for the setting.
* @example
* ```js
* const isEnabled = useSetting( 'typography.dropCap' );
* ```
*/
function useSetting(path) {
external_wp_deprecated_default()('wp.blockEditor.useSetting', {
since: '6.5',
alternative: 'wp.blockEditor.useSettings',
note: 'The new useSettings function can retrieve multiple settings at once, with better performance.'
});
const [value] = use_settings_useSettings(path);
return value;
}
;// external ["wp","styleEngine"]
const external_wp_styleEngine_namespaceObject = window["wp"]["styleEngine"];
;// ./node_modules/@wordpress/block-editor/build-module/components/font-sizes/fluid-utils.js
/**
* The fluid utilities must match the backend equivalent.
* See: gutenberg_get_typography_font_size_value() in lib/block-supports/typography.php
* ---------------------------------------------------------------
*/
// Defaults.
const DEFAULT_MAXIMUM_VIEWPORT_WIDTH = '1600px';
const DEFAULT_MINIMUM_VIEWPORT_WIDTH = '320px';
const DEFAULT_SCALE_FACTOR = 1;
const DEFAULT_MINIMUM_FONT_SIZE_FACTOR_MIN = 0.25;
const DEFAULT_MINIMUM_FONT_SIZE_FACTOR_MAX = 0.75;
const DEFAULT_MINIMUM_FONT_SIZE_LIMIT = '14px';
/**
* Computes a fluid font-size value that uses clamp(). A minimum and maximum
* font size OR a single font size can be specified.
*
* If a single font size is specified, it is scaled up and down using a logarithmic scale.
*
* @example
* ```js
* // Calculate fluid font-size value from a minimum and maximum value.
* const fontSize = getComputedFluidTypographyValue( {
* minimumFontSize: '20px',
* maximumFontSize: '45px'
* } );
* // Calculate fluid font-size value from a single font size.
* const fontSize = getComputedFluidTypographyValue( {
* fontSize: '30px',
* } );
* ```
*
* @param {Object} args
* @param {?string} args.minimumViewportWidth Minimum viewport size from which type will have fluidity. Optional if fontSize is specified.
* @param {?string} args.maximumViewportWidth Maximum size up to which type will have fluidity. Optional if fontSize is specified.
* @param {string|number} [args.fontSize] Size to derive maximumFontSize and minimumFontSize from, if necessary. Optional if minimumFontSize and maximumFontSize are specified.
* @param {?string} args.maximumFontSize Maximum font size for any clamp() calculation. Optional.
* @param {?string} args.minimumFontSize Minimum font size for any clamp() calculation. Optional.
* @param {?number} args.scaleFactor A scale factor to determine how fast a font scales within boundaries. Optional.
* @param {?string} args.minimumFontSizeLimit The smallest a calculated font size may be. Optional.
*
* @return {string|null} A font-size value using clamp().
*/
function getComputedFluidTypographyValue({
minimumFontSize,
maximumFontSize,
fontSize,
minimumViewportWidth = DEFAULT_MINIMUM_VIEWPORT_WIDTH,
maximumViewportWidth = DEFAULT_MAXIMUM_VIEWPORT_WIDTH,
scaleFactor = DEFAULT_SCALE_FACTOR,
minimumFontSizeLimit
}) {
// Validate incoming settings and set defaults.
minimumFontSizeLimit = !!getTypographyValueAndUnit(minimumFontSizeLimit) ? minimumFontSizeLimit : DEFAULT_MINIMUM_FONT_SIZE_LIMIT;
/*
* Calculates missing minimumFontSize and maximumFontSize from
* defaultFontSize if provided.
*/
if (fontSize) {
// Parses default font size.
const fontSizeParsed = getTypographyValueAndUnit(fontSize);
// Protect against invalid units.
if (!fontSizeParsed?.unit) {
return null;
}
// Parses the minimum font size limit, so we can perform checks using it.
const minimumFontSizeLimitParsed = getTypographyValueAndUnit(minimumFontSizeLimit, {
coerceTo: fontSizeParsed.unit
});
// Don't enforce minimum font size if a font size has explicitly set a min and max value.
if (!!minimumFontSizeLimitParsed?.value && !minimumFontSize && !maximumFontSize) {
/*
* If a minimum size was not passed to this function
* and the user-defined font size is lower than $minimum_font_size_limit,
* do not calculate a fluid value.
*/
if (fontSizeParsed?.value <= minimumFontSizeLimitParsed?.value) {
return null;
}
}
// If no fluid max font size is available use the incoming value.
if (!maximumFontSize) {
maximumFontSize = `${fontSizeParsed.value}${fontSizeParsed.unit}`;
}
/*
* If no minimumFontSize is provided, create one using
* the given font size multiplied by the min f
Showing 512.00 KB of 2.60 MB. Use Edit/Download for full content.
Directory Contents
Dirs: 3 × Files: 118