New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@wordpress/interactivity

Package Overview
Dependencies
Maintainers
24
Versions
80
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@wordpress/interactivity - npm Package Compare versions

Comparing version 5.7.0 to 6.0.0

src/init.ts

85

build-module/directives.js
// eslint-disable-next-line eslint-comments/disable-enable-pair
/* eslint-disable react-hooks/exhaustive-deps */
/* @jsx createElement */
/**

@@ -16,8 +14,6 @@ * External dependencies

*/
import { useWatch, useInit } from './utils';
import { useWatch, useInit, kebabToCamelCase, warn, yieldToMain } from './utils';
import { directive, getScope, getEvaluate } from './hooks';
import { kebabToCamelCase } from './utils/kebab-to-camelcase';
import { warn } from './utils/warn';
// Assigned objects should be ignore during proxification.
// Assigned objects should be ignored during proxification.
const contextAssignedObjects = new WeakMap();

@@ -200,5 +196,37 @@

};
/**
* Creates a directive that adds an async event listener to the global window or
* document object.
*
* @param type 'window' or 'document'
*/
const getGlobalAsyncEventDirective = type => {
return ({
directives,
evaluate
}) => {
directives[`on-async-${type}`].filter(({
suffix
}) => suffix !== 'default').forEach(entry => {
const eventName = entry.suffix.split('--', 1)[0];
useInit(() => {
const cb = async event => {
await yieldToMain();
evaluate(entry, event);
};
const globalVar = type === 'window' ? window : document;
globalVar.addEventListener(eventName, cb, {
passive: true
});
return () => globalVar.removeEventListener(eventName, cb);
});
});
};
};
export default (() => {
// data-wp-context
directive('context', ({
directive('context',
// @ts-ignore-next-line
({
directives: {

@@ -289,4 +317,8 @@ context

events.forEach((entries, eventType) => {
const existingHandler = element.props[`on${eventType}`];
element.props[`on${eventType}`] = event => {
entries.forEach(entry => {
if (existingHandler) {
existingHandler(event);
}
evaluate(entry, event);

@@ -298,2 +330,34 @@ });

// data-wp-on-async--[event]
directive('on-async', ({
directives: {
'on-async': onAsync
},
element,
evaluate
}) => {
const events = new Map();
onAsync.filter(({
suffix
}) => suffix !== 'default').forEach(entry => {
const event = entry.suffix.split('--')[0];
if (!events.has(event)) {
events.set(event, new Set());
}
events.get(event).add(entry);
});
events.forEach((entries, eventType) => {
const existingHandler = element.props[`on${eventType}`];
element.props[`on${eventType}`] = event => {
if (existingHandler) {
existingHandler(event);
}
entries.forEach(async entry => {
await yieldToMain();
evaluate(entry, event);
});
};
});
});
// data-wp-on-window--[event]

@@ -304,2 +368,7 @@ directive('on-window', getGlobalEventDirective('window'));

// data-wp-on-async-window--[event]
directive('on-async-window', getGlobalAsyncEventDirective('window'));
// data-wp-on-async-document--[event]
directive('on-async-document', getGlobalAsyncEventDirective('document'));
// data-wp-class--[classname]

@@ -537,3 +606,3 @@ directive('class', ({

value: mergedContext,
key: key
key
}, element.props.content);

@@ -540,0 +609,0 @@ });

12

build-module/hooks.js

@@ -1,3 +0,1 @@

/* @jsx createElement */
// eslint-disable-next-line eslint-comments/disable-enable-pair

@@ -15,3 +13,3 @@ /* eslint-disable react-hooks/exhaustive-deps */

import { store, stores, universalUnlock } from './store';
import { warn } from './utils/warn';
import { warn } from './utils';
// Main context.

@@ -177,3 +175,3 @@ const context = createContext({});

if (!namespace) {
warn(`The "namespace" cannot be "{}", "null" or an empty string. Path: ${path}`);
warn(`Namespace missing for "${path}". The value for that path won't be resolved.`);
return;

@@ -259,6 +257,6 @@ }

const children = nextPriorityLevels.length > 0 ? createElement(Directives, {
directives: directives,
directives,
priorityLevels: nextPriorityLevels,
element: element,
originalProps: originalProps,
element,
originalProps,
previousScope: scope

@@ -265,0 +263,0 @@ }) : element;

@@ -9,3 +9,3 @@ /**

import { toVdom, hydratedIslands } from './vdom';
import { createRootFragment } from './utils';
import { createRootFragment, yieldToMain } from './utils';
import { directivePrefix } from './constants';

@@ -16,2 +16,5 @@

export const getRegionRootFragment = region => {
if (!region.parentElement) {
throw Error('The passed region should be an element with a parent.');
}
if (!regionRootFragments.has(region)) {

@@ -22,8 +25,2 @@ regionRootFragments.set(region, createRootFragment(region.parentElement, region));

};
function yieldToMain() {
return new Promise(resolve => {
// TODO: Use scheduler.yield() when available.
setTimeout(resolve, 0);
});
}

@@ -30,0 +27,0 @@ // Initial vDOM regions associated with its DOM element.

@@ -250,9 +250,11 @@ /**

export const parseInitialData = (dom = document) => {
const storeTag = dom.querySelector(`script[type="application/json"]#wp-interactivity-data`);
if (storeTag?.textContent) {
var _dom$getElementById;
const jsonDataScriptTag = // Preferred Script Module data passing form
(_dom$getElementById = dom.getElementById('wp-scriptmodule-data_@wordpress/interactivity')) !== null && _dom$getElementById !== void 0 ? _dom$getElementById :
// Legacy form
dom.getElementById('wp-interactivity-data');
if (jsonDataScriptTag?.textContent) {
try {
return JSON.parse(storeTag.textContent);
} catch (e) {
// Do nothing.
}
return JSON.parse(jsonDataScriptTag.textContent);
} catch {}
}

@@ -259,0 +261,0 @@ return {};

@@ -33,2 +33,14 @@ /**

/**
* Returns a promise that resolves after yielding to main.
*
* @return Promise
*/
export const yieldToMain = () => {
return new Promise(resolve => {
// TODO: Use scheduler.yield() when available.
setTimeout(resolve, 0);
});
};
/**
* Creates a Flusher object that can be used to flush computed values and notify listeners.

@@ -260,2 +272,42 @@ *

};
/**
* Transforms a kebab-case string to camelCase.
*
* @param str The kebab-case string to transform to camelCase.
* @return The transformed camelCase string.
*/
export function kebabToCamelCase(str) {
return str.replace(/^-+|-+$/g, '').toLowerCase().replace(/-([a-z])/g, function (_match, group1) {
return group1.toUpperCase();
});
}
const logged = new Set();
/**
* Shows a warning with `message` if environment is not `production`.
*
* Based on the `@wordpress/warning` package.
*
* @param message Message to show in the warning.
*/
export const warn = message => {
if (globalThis.SCRIPT_DEBUG) {
if (logged.has(message)) {
return;
}
// eslint-disable-next-line no-console
console.warn(message);
// Throwing an error and catching it immediately to improve debugging
// A consumer can use 'pause on caught exceptions'
try {
throw Error(message);
} catch (e) {
// Do nothing.
}
logged.add(message);
}
};
//# sourceMappingURL=utils.js.map

@@ -9,3 +9,3 @@ /**

import { directivePrefix as p } from './constants';
import { warn } from './utils/warn';
import { warn } from './utils';
const ignoreAttr = `data-${p}-ignore`;

@@ -19,2 +19,3 @@ const islandAttr = `data-${p}-interactive`;

};
const isObject = item => Boolean(item && typeof item === 'object' && item.constructor === Object);

@@ -38,3 +39,3 @@ // Regular expression for directive parsing.

// forward slashes. References don't have any restrictions.
const nsPathRegExp = /^(?<namespace>[\w_\/-]+)::(?<value>.+)$/;
const nsPathRegExp = /^([\w_\/-]+)::(.+)$/;
export const hydratedIslands = new WeakSet();

@@ -87,2 +88,3 @@

const attributeName = attributes[i].name;
const attributeValue = attributes[i].value;
if (attributeName[fullPrefix.length] && attributeName.slice(0, fullPrefix.length) === fullPrefix) {

@@ -92,9 +94,10 @@ if (attributeName === ignoreAttr) {

} else {
var _regexCaptureGroups$n, _regexCaptureGroups$v;
const regexCaptureGroups = nsPathRegExp.exec(attributes[i].value)?.groups;
const namespace = (_regexCaptureGroups$n = regexCaptureGroups?.namespace) !== null && _regexCaptureGroups$n !== void 0 ? _regexCaptureGroups$n : null;
let value = (_regexCaptureGroups$v = regexCaptureGroups?.value) !== null && _regexCaptureGroups$v !== void 0 ? _regexCaptureGroups$v : attributes[i].value;
var _regexResult$, _regexResult$2;
const regexResult = nsPathRegExp.exec(attributeValue);
const namespace = (_regexResult$ = regexResult?.[1]) !== null && _regexResult$ !== void 0 ? _regexResult$ : null;
let value = (_regexResult$2 = regexResult?.[2]) !== null && _regexResult$2 !== void 0 ? _regexResult$2 : attributeValue;
try {
value = value && JSON.parse(value);
} catch (e) {}
const parsedValue = JSON.parse(value);
value = isObject(parsedValue) ? parsedValue : value;
} catch {}
if (attributeName === islandAttr) {

@@ -113,3 +116,3 @@ island = true;

}
props[attributeName] = attributes[i].value;
props[attributeName] = attributeValue;
}

@@ -132,3 +135,3 @@ if (ignore && !island) {

if (directiveMatch === null) {
warn(`Invalid directive: ${name}.`);
warn(`Found malformed directive name: ${name}.`);
return obj;

@@ -135,0 +138,0 @@ }

@@ -6,3 +6,3 @@ /**

import type { VNode, Context, RefObject } from 'preact';
interface DirectiveEntry {
export interface DirectiveEntry {
value: string | object;

@@ -9,0 +9,0 @@ namespace: string;

@@ -1,4 +0,8 @@

export function getRegionRootFragment(region: any): any;
export const initialVdom: WeakMap<WeakKey, any>;
export function init(): Promise<void>;
/**
* External dependencies
*/
import { type ContainerNode, type ComponentChild } from 'preact';
export declare const getRegionRootFragment: (region: Element) => ContainerNode;
export declare const initialVdom: WeakMap<Element, ComponentChild[]>;
export declare const init: () => Promise<void>;
//# sourceMappingURL=init.d.ts.map

@@ -8,3 +8,3 @@ export declare const stores: Map<any, any>;

*/
export declare const getConfig: (namespace: string) => any;
export declare const getConfig: (namespace?: string) => any;
interface StoreOptions {

@@ -11,0 +11,0 @@ /**

@@ -6,2 +6,8 @@ /**

/**
* Returns a promise that resolves after yielding to main.
*
* @return Promise
*/
export declare const yieldToMain: () => Promise<unknown>;
/**
* Custom hook that executes a callback function whenever a signal is triggered.

@@ -125,2 +131,17 @@ * Version of `useSignalEffect` with a `useEffect`-like execution. This hook

};
/**
* Transforms a kebab-case string to camelCase.
*
* @param str The kebab-case string to transform to camelCase.
* @return The transformed camelCase string.
*/
export declare function kebabToCamelCase(str: string): string;
/**
* Shows a warning with `message` if environment is not `production`.
*
* Based on the `@wordpress/warning` package.
*
* @param message Message to show in the warning.
*/
export declare const warn: (message: string) => void;
//# sourceMappingURL=utils.d.ts.map

@@ -12,9 +12,5 @@ "use strict";

var _hooks2 = require("./hooks");
var _kebabToCamelcase = require("./utils/kebab-to-camelcase");
var _warn = require("./utils/warn");
// eslint-disable-next-line eslint-comments/disable-enable-pair
/* eslint-disable react-hooks/exhaustive-deps */
/* @jsx createElement */
/**

@@ -28,3 +24,3 @@ * External dependencies

// Assigned objects should be ignore during proxification.
// Assigned objects should be ignored during proxification.
const contextAssignedObjects = new WeakMap();

@@ -207,5 +203,37 @@

};
/**
* Creates a directive that adds an async event listener to the global window or
* document object.
*
* @param type 'window' or 'document'
*/
const getGlobalAsyncEventDirective = type => {
return ({
directives,
evaluate
}) => {
directives[`on-async-${type}`].filter(({
suffix
}) => suffix !== 'default').forEach(entry => {
const eventName = entry.suffix.split('--', 1)[0];
(0, _utils.useInit)(() => {
const cb = async event => {
await (0, _utils.yieldToMain)();
evaluate(entry, event);
};
const globalVar = type === 'window' ? window : document;
globalVar.addEventListener(eventName, cb, {
passive: true
});
return () => globalVar.removeEventListener(eventName, cb);
});
});
};
};
var _default = () => {
// data-wp-context
(0, _hooks2.directive)('context', ({
(0, _hooks2.directive)('context',
// @ts-ignore-next-line
({
directives: {

@@ -237,3 +265,3 @@ context

if (!isPlainObject(value)) {
(0, _warn.warn)(`The value of data-wp-context in "${namespace}" store must be a valid stringified JSON object.`);
(0, _utils.warn)(`The value of data-wp-context in "${namespace}" store must be a valid stringified JSON object.`);
}

@@ -297,4 +325,8 @@ updateSignals(currentValue.current, {

events.forEach((entries, eventType) => {
const existingHandler = element.props[`on${eventType}`];
element.props[`on${eventType}`] = event => {
entries.forEach(entry => {
if (existingHandler) {
existingHandler(event);
}
evaluate(entry, event);

@@ -306,2 +338,34 @@ });

// data-wp-on-async--[event]
(0, _hooks2.directive)('on-async', ({
directives: {
'on-async': onAsync
},
element,
evaluate
}) => {
const events = new Map();
onAsync.filter(({
suffix
}) => suffix !== 'default').forEach(entry => {
const event = entry.suffix.split('--')[0];
if (!events.has(event)) {
events.set(event, new Set());
}
events.get(event).add(entry);
});
events.forEach((entries, eventType) => {
const existingHandler = element.props[`on${eventType}`];
element.props[`on${eventType}`] = event => {
if (existingHandler) {
existingHandler(event);
}
entries.forEach(async entry => {
await (0, _utils.yieldToMain)();
evaluate(entry, event);
});
};
});
});
// data-wp-on-window--[event]

@@ -312,2 +376,7 @@ (0, _hooks2.directive)('on-window', getGlobalEventDirective('window'));

// data-wp-on-async-window--[event]
(0, _hooks2.directive)('on-async-window', getGlobalAsyncEventDirective('window'));
// data-wp-on-async-document--[event]
(0, _hooks2.directive)('on-async-document', getGlobalAsyncEventDirective('document'));
// data-wp-class--[classname]

@@ -528,3 +597,3 @@ (0, _hooks2.directive)('class', ({

return list.map(item => {
const itemProp = suffix === 'default' ? 'item' : (0, _kebabToCamelcase.kebabToCamelCase)(suffix);
const itemProp = suffix === 'default' ? 'item' : (0, _utils.kebabToCamelCase)(suffix);
const itemContext = (0, _deepsignal.deepSignal)({

@@ -546,3 +615,3 @@ [namespace]: {}

value: mergedContext,
key: key
key
}, element.props.content);

@@ -549,0 +618,0 @@ });

@@ -10,5 +10,3 @@ "use strict";

var _store = require("./store");
var _warn = require("./utils/warn");
/* @jsx createElement */
var _utils = require("./utils");
// eslint-disable-next-line eslint-comments/disable-enable-pair

@@ -194,3 +192,3 @@ /* eslint-disable react-hooks/exhaustive-deps */

if (!namespace) {
(0, _warn.warn)(`The "namespace" cannot be "{}", "null" or an empty string. Path: ${path}`);
(0, _utils.warn)(`Namespace missing for "${path}". The value for that path won't be resolved.`);
return;

@@ -277,6 +275,6 @@ }

const children = nextPriorityLevels.length > 0 ? (0, _preact.h)(Directives, {
directives: directives,
directives,
priorityLevels: nextPriorityLevels,
element: element,
originalProps: originalProps,
element,
originalProps,
previousScope: scope

@@ -283,0 +281,0 @@ }) : element;

@@ -22,2 +22,5 @@ "use strict";

const getRegionRootFragment = region => {
if (!region.parentElement) {
throw Error('The passed region should be an element with a parent.');
}
if (!regionRootFragments.has(region)) {

@@ -28,11 +31,5 @@ regionRootFragments.set(region, (0, _utils.createRootFragment)(region.parentElement, region));

};
exports.getRegionRootFragment = getRegionRootFragment;
function yieldToMain() {
return new Promise(resolve => {
// TODO: Use scheduler.yield() when available.
setTimeout(resolve, 0);
});
}
// Initial vDOM regions associated with its DOM element.
exports.getRegionRootFragment = getRegionRootFragment;
const initialVdom = exports.initialVdom = new WeakMap();

@@ -45,7 +42,7 @@

if (!_vdom.hydratedIslands.has(node)) {
await yieldToMain();
await (0, _utils.yieldToMain)();
const fragment = getRegionRootFragment(node);
const vdom = (0, _vdom.toVdom)(node);
initialVdom.set(node, vdom);
await yieldToMain();
await (0, _utils.yieldToMain)();
(0, _preact.hydrate)(vdom, fragment);

@@ -52,0 +49,0 @@ }

@@ -260,9 +260,11 @@ "use strict";

const parseInitialData = (dom = document) => {
const storeTag = dom.querySelector(`script[type="application/json"]#wp-interactivity-data`);
if (storeTag?.textContent) {
var _dom$getElementById;
const jsonDataScriptTag = // Preferred Script Module data passing form
(_dom$getElementById = dom.getElementById('wp-scriptmodule-data_@wordpress/interactivity')) !== null && _dom$getElementById !== void 0 ? _dom$getElementById :
// Legacy form
dom.getElementById('wp-interactivity-data');
if (jsonDataScriptTag?.textContent) {
try {
return JSON.parse(storeTag.textContent);
} catch (e) {
// Do nothing.
}
return JSON.parse(jsonDataScriptTag.textContent);
} catch {}
}

@@ -269,0 +271,0 @@ return {};

@@ -7,2 +7,3 @@ "use strict";

exports.createRootFragment = void 0;
exports.kebabToCamelCase = kebabToCamelCase;
exports.useCallback = useCallback;

@@ -15,3 +16,5 @@ exports.useEffect = useEffect;

exports.useWatch = useWatch;
exports.warn = void 0;
exports.withScope = withScope;
exports.yieldToMain = void 0;
var _hooks = require("preact/hooks");

@@ -50,2 +53,14 @@ var _signals = require("@preact/signals");

/**
* Returns a promise that resolves after yielding to main.
*
* @return Promise
*/
const yieldToMain = () => {
return new Promise(resolve => {
// TODO: Use scheduler.yield() when available.
setTimeout(resolve, 0);
});
};
/**
* Creates a Flusher object that can be used to flush computed values and notify listeners.

@@ -62,2 +77,3 @@ *

*/
exports.yieldToMain = yieldToMain;
function createFlusher(compute, notify) {

@@ -278,3 +294,44 @@ let flush = () => undefined;

};
/**
* Transforms a kebab-case string to camelCase.
*
* @param str The kebab-case string to transform to camelCase.
* @return The transformed camelCase string.
*/
exports.createRootFragment = createRootFragment;
function kebabToCamelCase(str) {
return str.replace(/^-+|-+$/g, '').toLowerCase().replace(/-([a-z])/g, function (_match, group1) {
return group1.toUpperCase();
});
}
const logged = new Set();
/**
* Shows a warning with `message` if environment is not `production`.
*
* Based on the `@wordpress/warning` package.
*
* @param message Message to show in the warning.
*/
const warn = message => {
if (globalThis.SCRIPT_DEBUG) {
if (logged.has(message)) {
return;
}
// eslint-disable-next-line no-console
console.warn(message);
// Throwing an error and catching it immediately to improve debugging
// A consumer can use 'pause on caught exceptions'
try {
throw Error(message);
} catch (e) {
// Do nothing.
}
logged.add(message);
}
};
exports.warn = warn;
//# sourceMappingURL=utils.js.map

@@ -10,3 +10,3 @@ "use strict";

var _constants = require("./constants");
var _warn = require("./utils/warn");
var _utils = require("./utils");
/**

@@ -28,2 +28,3 @@ * External dependencies

};
const isObject = item => Boolean(item && typeof item === 'object' && item.constructor === Object);

@@ -47,3 +48,3 @@ // Regular expression for directive parsing.

// forward slashes. References don't have any restrictions.
const nsPathRegExp = /^(?<namespace>[\w_\/-]+)::(?<value>.+)$/;
const nsPathRegExp = /^([\w_\/-]+)::(.+)$/;
const hydratedIslands = exports.hydratedIslands = new WeakSet();

@@ -96,2 +97,3 @@

const attributeName = attributes[i].name;
const attributeValue = attributes[i].value;
if (attributeName[fullPrefix.length] && attributeName.slice(0, fullPrefix.length) === fullPrefix) {

@@ -101,9 +103,10 @@ if (attributeName === ignoreAttr) {

} else {
var _regexCaptureGroups$n, _regexCaptureGroups$v;
const regexCaptureGroups = nsPathRegExp.exec(attributes[i].value)?.groups;
const namespace = (_regexCaptureGroups$n = regexCaptureGroups?.namespace) !== null && _regexCaptureGroups$n !== void 0 ? _regexCaptureGroups$n : null;
let value = (_regexCaptureGroups$v = regexCaptureGroups?.value) !== null && _regexCaptureGroups$v !== void 0 ? _regexCaptureGroups$v : attributes[i].value;
var _regexResult$, _regexResult$2;
const regexResult = nsPathRegExp.exec(attributeValue);
const namespace = (_regexResult$ = regexResult?.[1]) !== null && _regexResult$ !== void 0 ? _regexResult$ : null;
let value = (_regexResult$2 = regexResult?.[2]) !== null && _regexResult$2 !== void 0 ? _regexResult$2 : attributeValue;
try {
value = value && JSON.parse(value);
} catch (e) {}
const parsedValue = JSON.parse(value);
value = isObject(parsedValue) ? parsedValue : value;
} catch {}
if (attributeName === islandAttr) {

@@ -122,3 +125,3 @@ island = true;

}
props[attributeName] = attributes[i].value;
props[attributeName] = attributeValue;
}

@@ -141,3 +144,3 @@ if (ignore && !island) {

if (directiveMatch === null) {
(0, _warn.warn)(`Invalid directive: ${name}.`);
(0, _utils.warn)(`Found malformed directive name: ${name}.`);
return obj;

@@ -144,0 +147,0 @@ }

@@ -5,2 +5,17 @@ <!-- Learn how to maintain this file at https://github.com/WordPress/gutenberg/tree/HEAD/packages#maintaining-changelogs. -->

## 6.0.0 (2024-05-31)
### New Features
- Introduce `wp-on-async` directive as performant alternative over synchronous `wp-on` directive. ([#61885](https://github.com/WordPress/gutenberg/pull/61885))
### Breaking Changes
- Variables like `process.env.IS_GUTENBERG_PLUGIN` have been replaced by `globalThis.IS_GUTENBERG_PLUGIN`. Build systems using `process.env` should be updated ([#61486](https://github.com/WordPress/gutenberg/pull/61486)).
- Increase the minimum required Node.js version to v18.12.0 matching long-term support releases ([#31270](https://github.com/WordPress/gutenberg/pull/61930)). Learn more about [Node.js releases](https://nodejs.org/en/about/previous-releases).
### Bug fixes
- Fix null and number strings as namespaces runtime error. ([#61960](https://github.com/WordPress/gutenberg/pull/61960/))
## 5.7.0 (2024-05-16)

@@ -14,5 +29,5 @@

- Allow multiple event handlers for the same type with `data-wp-on-document` and `data-wp-on-window`. ([#61009](https://github.com/WordPress/gutenberg/pull/61009))
- Prevent wrong written directives from killing the runtime ([#61249](https://github.com/WordPress/gutenberg/pull/61249))
- Prevent empty namespace or different namespaces from killing the runtime ([#61409](https://github.com/WordPress/gutenberg/pull/61409))
- Allow multiple event handlers for the same type with `data-wp-on-document` and `data-wp-on-window`. ([#61009](https://github.com/WordPress/gutenberg/pull/61009))
- Prevent wrong written directives from killing the runtime ([#61249](https://github.com/WordPress/gutenberg/pull/61249))
- Prevent empty namespace or different namespaces from killing the runtime ([#61409](https://github.com/WordPress/gutenberg/pull/61409))

@@ -25,3 +40,3 @@ ## 5.6.0 (2024-05-02)

- Improve data-wp-context debugging by validating it as a stringified JSON Object. ([#61045](https://github.com/WordPress/gutenberg/pull/61045))
- Improve data-wp-context debugging by validating it as a stringified JSON Object. ([#61045](https://github.com/WordPress/gutenberg/pull/61045))

@@ -28,0 +43,0 @@ ### Bug Fixes

{
"name": "@wordpress/interactivity",
"version": "5.7.0",
"version": "6.0.0",
"description": "Package that provides a standard and simple way to handle the frontend interactivity of Gutenberg blocks.",

@@ -22,3 +22,4 @@ "author": "The WordPress Contributors",

"engines": {
"node": ">=12"
"node": ">=18.12.0",
"npm": ">=8.19.2"
},

@@ -37,3 +38,3 @@ "main": "build/index.js",

},
"gitHead": "42f38f287506a6b3ed8ccba839b18ad066821044"
"gitHead": "2f30cddff15723ac7017fd009fc5913b7b419400"
}

@@ -18,3 +18,2 @@ /**

} from './hooks';
const isObject = ( item: unknown ): item is Record< string, unknown > =>

@@ -181,3 +180,3 @@ Boolean( item && typeof item === 'object' && item.constructor === Object );

*/
export const getConfig = ( namespace: string ) =>
export const getConfig = ( namespace?: string ) =>
storeConfigs.get( namespace || getNamespace() ) || {};

@@ -325,11 +324,11 @@

export const parseInitialData = ( dom = document ) => {
const storeTag = dom.querySelector(
`script[type="application/json"]#wp-interactivity-data`
);
if ( storeTag?.textContent ) {
const jsonDataScriptTag =
// Preferred Script Module data passing form
dom.getElementById( 'wp-scriptmodule-data_@wordpress/interactivity' ) ??
// Legacy form
dom.getElementById( 'wp-interactivity-data' );
if ( jsonDataScriptTag?.textContent ) {
try {
return JSON.parse( storeTag.textContent );
} catch ( e ) {
// Do nothing.
}
return JSON.parse( jsonDataScriptTag.textContent );
} catch {}
}

@@ -336,0 +335,0 @@ return {};

@@ -53,2 +53,14 @@ /**

/**
* Returns a promise that resolves after yielding to main.
*
* @return Promise
*/
export const yieldToMain = () => {
return new Promise( ( resolve ) => {
// TODO: Use scheduler.yield() when available.
setTimeout( resolve, 0 );
} );
};
/**
* Creates a Flusher object that can be used to flush computed values and notify listeners.

@@ -294,1 +306,45 @@ *

};
/**
* Transforms a kebab-case string to camelCase.
*
* @param str The kebab-case string to transform to camelCase.
* @return The transformed camelCase string.
*/
export function kebabToCamelCase( str: string ): string {
return str
.replace( /^-+|-+$/g, '' )
.toLowerCase()
.replace( /-([a-z])/g, function ( _match, group1: string ) {
return group1.toUpperCase();
} );
}
const logged: Set< string > = new Set();
/**
* Shows a warning with `message` if environment is not `production`.
*
* Based on the `@wordpress/warning` package.
*
* @param message Message to show in the warning.
*/
export const warn = ( message: string ): void => {
if ( globalThis.SCRIPT_DEBUG ) {
if ( logged.has( message ) ) {
return;
}
// eslint-disable-next-line no-console
console.warn( message );
// Throwing an error and catching it immediately to improve debugging
// A consumer can use 'pause on caught exceptions'
try {
throw Error( message );
} catch ( e ) {
// Do nothing.
}
logged.add( message );
}
};

@@ -9,3 +9,3 @@ /**

import { directivePrefix as p } from './constants';
import { warn } from './utils/warn';
import { warn } from './utils';

@@ -17,2 +17,4 @@ const ignoreAttr = `data-${ p }-ignore`;

const currentNamespace = () => namespaces[ namespaces.length - 1 ] ?? null;
const isObject = ( item: unknown ): item is Record< string, unknown > =>
Boolean( item && typeof item === 'object' && item.constructor === Object );

@@ -37,3 +39,3 @@ // Regular expression for directive parsing.

// forward slashes. References don't have any restrictions.
const nsPathRegExp = /^(?<namespace>[\w_\/-]+)::(?<value>.+)$/;
const nsPathRegExp = /^([\w_\/-]+)::(.+)$/;

@@ -94,2 +96,3 @@ export const hydratedIslands = new WeakSet();

const attributeName = attributes[ i ].name;
const attributeValue = attributes[ i ].value;
if (

@@ -102,11 +105,9 @@ attributeName[ fullPrefix.length ] &&

} else {
const regexCaptureGroups = nsPathRegExp.exec(
attributes[ i ].value
)?.groups;
const namespace = regexCaptureGroups?.namespace ?? null;
let value: any =
regexCaptureGroups?.value ?? attributes[ i ].value;
const regexResult = nsPathRegExp.exec( attributeValue );
const namespace = regexResult?.[ 1 ] ?? null;
let value: any = regexResult?.[ 2 ] ?? attributeValue;
try {
value = value && JSON.parse( value );
} catch ( e ) {}
const parsedValue = JSON.parse( value );
value = isObject( parsedValue ) ? parsedValue : value;
} catch {}
if ( attributeName === islandAttr ) {

@@ -129,3 +130,3 @@ island = true;

}
props[ attributeName ] = attributes[ i ].value;
props[ attributeName ] = attributeValue;
}

@@ -151,3 +152,3 @@

if ( directiveMatch === null ) {
warn( `Invalid directive: ${ name }.` );
warn( `Found malformed directive name: ${ name }.` );
return obj;

@@ -154,0 +155,0 @@ }

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc