Skip to content

Commit

Permalink
Add types for shortcode package (#67416)
Browse files Browse the repository at this point in the history
* Add types for shortcode package

* Remove WP Prefix

* Update CHANGELOG.md

Co-authored-by: manzoorwanijk <[email protected]>
Co-authored-by: gziolo <[email protected]>
  • Loading branch information
3 people authored and michalczaplinski committed Dec 5, 2024
1 parent 06a47c3 commit 0b1d9ef
Show file tree
Hide file tree
Showing 7 changed files with 245 additions and 51 deletions.
4 changes: 4 additions & 0 deletions packages/shortcode/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

## Enhancements

- The package now has built-in TypeScript definitions 🎉 ([#67416](https://github.com/WordPress/gutenberg/pull/67416))

## 4.13.0 (2024-11-27)

## 4.12.0 (2024-11-16)
Expand Down
18 changes: 7 additions & 11 deletions packages/shortcode/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,17 @@ _Parameters_

_Returns_

- `WPShortcodeAttrs`: Parsed shortcode attributes.
- `import('./types').ShortcodeAttrs`: Parsed shortcode attributes.

### default

Creates a shortcode instance.

To access a raw representation of a shortcode, pass an `options` object, containing a `tag` string, a string or object of `attrs`, a string indicating the `type` of the shortcode ('single', 'self-closing', or 'closed'), and a `content` string.

_Parameters_

- _options_ `Object`: Options as described.

_Returns_
_Type_

- `WPShortcode`: Shortcode instance.
- `import('./types').shortcode`Shortcode instance.

### fromMatch

Expand All @@ -56,11 +52,11 @@ Accepts a `match` object from calling `regexp.exec()` on a `RegExp` generated by

_Parameters_

- _match_ `Array`: Match array.
- _match_ `import('./types').Match`: Match array.

_Returns_

- `WPShortcode`: Shortcode instance.
- `InstanceType<import('./types').shortcode>`: Shortcode instance.

### next

Expand All @@ -74,7 +70,7 @@ _Parameters_

_Returns_

- `WPShortcodeMatch | undefined`: Matched information.
- `import('./types').ShortcodeMatch | undefined`: Matched information.

### regexp

Expand Down Expand Up @@ -108,7 +104,7 @@ _Parameters_

- _tag_ `string`: Shortcode tag.
- _text_ `string`: Text to search.
- _callback_ `Function`: Function to process the match and return replacement string.
- _callback_ `import('./types').ReplaceCallback`: Function to process the match and return replacement string.

_Returns_

Expand Down
1 change: 1 addition & 0 deletions packages/shortcode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"module": "build-module/index.js",
"react-native": "src/index",
"wpScript": true,
"types": "build-types",
"dependencies": {
"@babel/runtime": "7.25.7",
"memize": "^2.0.1"
Expand Down
51 changes: 11 additions & 40 deletions packages/shortcode/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,7 @@
*/
import memize from 'memize';

/**
* Shortcode attributes object.
*
* @typedef {Object} WPShortcodeAttrs
*
* @property {Object} named Object with named attributes.
* @property {Array} numeric Array with numeric attributes.
*/

/**
* Shortcode object.
*
* @typedef {Object} WPShortcode
*
* @property {string} tag Shortcode tag.
* @property {WPShortcodeAttrs} attrs Shortcode attributes.
* @property {string} content Shortcode content.
* @property {string} type Shortcode type: `self-closing`,
* `closed`, or `single`.
*/

/**
* @typedef {Object} WPShortcodeMatch
*
* @property {number} index Index the shortcode is found at.
* @property {string} content Matched content.
* @property {WPShortcode} shortcode Shortcode instance of the match.
*/
export * from './types';

/**
* Find the next matching shortcode.
Expand All @@ -39,7 +12,7 @@ import memize from 'memize';
* @param {string} text Text to search.
* @param {number} index Index to start search from.
*
* @return {WPShortcodeMatch | undefined} Matched information.
* @return {import('./types').ShortcodeMatch | undefined} Matched information.
*/
export function next( tag, text, index = 0 ) {
const re = regexp( tag );
Expand Down Expand Up @@ -81,10 +54,10 @@ export function next( tag, text, index = 0 ) {
/**
* Replace matching shortcodes in a block of text.
*
* @param {string} tag Shortcode tag.
* @param {string} text Text to search.
* @param {Function} callback Function to process the match and return
* replacement string.
* @param {string} tag Shortcode tag.
* @param {string} text Text to search.
* @param {import('./types').ReplaceCallback} callback Function to process the match and return
* replacement string.
*
* @return {string} Text with shortcodes replaced.
*/
Expand Down Expand Up @@ -169,7 +142,7 @@ export function regexp( tag ) {
*
* @param {string} text Serialised shortcode attributes.
*
* @return {WPShortcodeAttrs} Parsed shortcode attributes.
* @return {import('./types').ShortcodeAttrs} Parsed shortcode attributes.
*/
export const attrs = memize( ( text ) => {
const named = {};
Expand Down Expand Up @@ -224,9 +197,9 @@ export const attrs = memize( ( text ) => {
* by `regexp()`. `match` can also be set to the `arguments` from a callback
* passed to `regexp.replace()`.
*
* @param {Array} match Match array.
* @param {import('./types').Match} match Match array.
*
* @return {WPShortcode} Shortcode instance.
* @return {InstanceType<import('./types').shortcode>} Shortcode instance.
*/
export function fromMatch( match ) {
let type;
Expand Down Expand Up @@ -255,9 +228,7 @@ export function fromMatch( match ) {
* the `type` of the shortcode ('single', 'self-closing', or 'closed'), and a
* `content` string.
*
* @param {Object} options Options as described.
*
* @return {WPShortcode} Shortcode instance.
* @type {import('./types').shortcode} Shortcode instance.
*/
const shortcode = Object.assign(
function ( options ) {
Expand Down Expand Up @@ -328,7 +299,7 @@ Object.assign( shortcode.prototype, {
* @param {(number|string)} attr Attribute key.
* @param {string} value Attribute value.
*
* @return {WPShortcode} Shortcode instance.
* @return {InstanceType< import('./types').shortcode >} Shortcode instance.
*/
set( attr, value ) {
this.attrs[ typeof attr === 'number' ? 'numeric' : 'named' ][ attr ] =
Expand Down
210 changes: 210 additions & 0 deletions packages/shortcode/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
/**
* Shortcode attributes object.
*/
export type ShortcodeAttrs = {
/**
* Object with named attributes.
*/
named: Record< string, string | undefined >;

/**
* Array with numeric attributes.
*/
numeric: string[];
};

export type ShortcodeMatch = {
/**
* Index the shortcode is found at.
*/
index: number;

/**
* Matched content.
*/
content: string;

/**
* Shortcode instance of the match.
*/
shortcode: Shortcode;
};

/**
* Shortcode options.
*/
export interface ShortcodeOptions {
/**
* Shortcode tag.
*/
tag: string;

/**
* Shortcode attributes.
*/
attrs?: Partial< ShortcodeAttrs > | string;

/**
* Shortcode content.
*/
content?: string;

/**
* Shortcode type: `self-closing`, `closed`, or `single`.
*/
type?: 'self-closing' | 'closed' | 'single';
}

/**
* Shortcode object.
*/
export interface Shortcode extends ShortcodeOptions {
/**
* Shortcode attributes.
*/
attrs: ShortcodeAttrs;
}

export type Match =
| NonNullable< ReturnType< RegExp[ 'exec' ] > >
| Array< string >;

export type ReplaceCallback = ( shortcode: Shortcode ) => string;

/**
* WordPress Shortcode instance.
*/
export interface shortcode {
new ( options: Partial< ShortcodeOptions > ): Shortcode & {
/**
* Transform the shortcode into a string.
*
* @return {string} String representation of the shortcode.
*/
string: () => string;

/**
* Get a shortcode attribute.
*
* Automatically detects whether `attr` is named or numeric and routes it
* accordingly.
*
* @param {(number|string)} attr Attribute key.
*
* @return {string} Attribute value.
*/
get: ( attr: string | number ) => string | undefined;

/**
* Set a shortcode attribute.
*
* Automatically detects whether `attr` is named or numeric and routes it
* accordingly.
*
* @param {(number|string)} attr Attribute key.
* @param {string} value Attribute value.
*
* @return {InstanceType< shortcode >} Shortcode instance.
*/
set: (
attr: string | number,
value: string
) => InstanceType< shortcode >;
};

/**
* Parse shortcode attributes.
*
* Shortcodes accept many types of attributes. These can chiefly be divided into
* named and numeric attributes:
*
* Named attributes are assigned on a key/value basis, while numeric attributes
* are treated as an array.
*
* Named attributes can be formatted as either `name="value"`, `name='value'`,
* or `name=value`. Numeric attributes can be formatted as `"value"` or just
* `value`.
*
* @param text Serialised shortcode attributes.
*
* @return Parsed shortcode attributes.
*/
attrs: ( text: string ) => ShortcodeAttrs;

/**
* Generate a Shortcode Object from a RegExp match.
*
* Accepts a `match` object from calling `regexp.exec()` on a `RegExp` generated
* by `regexp()`. `match` can also be set to the `arguments` from a callback
* passed to `regexp.replace()`.
*
* @param match Match array.
*
* @return Shortcode instance.
*/
fromMatch: ( match: Match ) => InstanceType< shortcode >;

/**
* Find the next matching shortcode.
*
* @param tag Shortcode tag.
* @param text Text to search.
* @param index Index to start search from.
*
* @return Matched information.
*/
next: (
tag: string,
text: string,
index?: number
) => ShortcodeMatch | undefined;

/**
* Generate a RegExp to identify a shortcode.
*
* The base regex is functionally equivalent to the one found in
* `get_shortcode_regex()` in `wp-includes/shortcodes.php`.
*
* Capture groups:
*
* 1. An extra `[` to allow for escaping shortcodes with double `[[]]`
* 2. The shortcode name
* 3. The shortcode argument list
* 4. The self closing `/`
* 5. The content of a shortcode when it wraps some content.
* 6. The closing tag.
* 7. An extra `]` to allow for escaping shortcodes with double `[[]]`
*
* @param tag Shortcode tag.
*
* @return Shortcode RegExp.
*/
regexp: ( tag: string ) => RegExp;

/**
* Replace matching shortcodes in a block of text.
*
* @param tag Shortcode tag.
* @param text Text to search.
* @param callback Function to process the match and return
* replacement string.
*
* @return Text with shortcodes replaced.
*/
replace: ( tag: string, text: string, callback: ReplaceCallback ) => string;

/**
* Generate a string from shortcode parameters.
*
* Creates a shortcode instance and returns a string.
*
* Accepts the same `options` as the `shortcode()` constructor, containing a
* `tag` string, a string or object of `attrs`, a boolean indicating whether to
* format the shortcode using a `single` tag, and a `content` string.
*
* @param options
*
* @return String representation of the shortcode.
*/
string: ( options: ShortcodeOptions ) => string;
}
11 changes: 11 additions & 0 deletions packages/shortcode/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"$schema": "https://json.schemastore.org/tsconfig.json",
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"rootDir": "src",
"declarationDir": "build-types",
"checkJs": false
},
"references": [],
"include": [ "src" ]
}
Loading

0 comments on commit 0b1d9ef

Please sign in to comment.